【MySQL精通之路】SQL优化(1)-查询优化(5)-引擎条件下推

1 介绍

这种优化提高了无索引列常量之间直接比较的效率。

在这种情况下,条件会**"向下推"到存储引擎** 进行评估。此优化只能由NDB存储引擎使用。

对于NDB集群 ,这种优化可以消除在集群的数据节点发布查询的MySQL服务器 之间通过网络发送不匹配行 的操作,并且可以将使用条件下推的查询速度提高5到10倍。

假设NDB Cluster表定义如下:

sql 复制代码
CREATE TABLE t1 (
    a INT,
    b INT,
    KEY(a)
) ENGINE=NDB;

引擎条件下推 可以与查询条件 一起使用,例如这里显示的查询,其中包括无索引列常量之间的比较:

sql 复制代码
SELECT a, b FROM t1 WHERE b = 10;

引擎状态下推的使用可以在EXPLAIN的输出中看到:

sql 复制代码
mysql> EXPLAIN SELECT a, b FROM t1 WHERE b = 10\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 10
        Extra: Using where with pushed condition

但是,引擎条件下推不能与以下查询一起使用:

sql 复制代码
SELECT a,b FROM t1 WHERE a = 10;

引擎条件下推不适用于此处,因为列a上存在索引。(索引访问方法会更有效,因此会优先选择)


当使用>或<运算符将索引列与常量进行比较时,也可以使用引擎条件下推:

sql 复制代码
mysql> EXPLAIN SELECT a, b FROM t1 WHERE a < 2\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
         type: range
possible_keys: a
          key: a
      key_len: 5
          ref: NULL
         rows: 2
        Extra: Using where with pushed condition

其他支持的引擎条件下推比较包括以下内容:

column[NOT] LIKEpattern

pattern必须是包含要匹配字符串文字;

有关语法,请参阅"字符串比较函数和运算符"。
column IS [NOT] NULL
column IN (value_list)

value_list中的每个项都必须是一个常量的文字值。
columnBETWEENconstant1ANDconstant2

constant1和constnt2必须分别为常量、文字值。

2.设置

在前面列表中的所有情况下,条件都可以转换为常量之间的一个或多个直接比较的形式。

默认情况下,引擎条件下推功能处于启用状态

要在服务器启动时禁用它,请将optimizer_switch系统变量engine_condition_pushdown标志设置为off。

例如,在my.cnf文件中,使用以下行:

sql 复制代码
[mysqld]
optimizer_switch=engine_condition_pushdown=off

在运行时,禁用条件下推,如下所示:

sql 复制代码
SET optimizer_switch='engine_condition_pushdown=off';

3.局限性

引擎条件下推受以下限制:

NDB存储引擎 支持引擎状态下推。
在NDB 8.0.18之前,仅支持 与计算结果为常数值的"常量 或**表达式"**进行比较。

在NDB 8.0.18及更高版本中,只要列的类型完全相同,包括相同的符号、长度、字符集、精度和小数位数,就可以相互比较。
比较中使用的列不能是任何BLOBTEXT类型 。这种排除也扩展到JSON、BITENUM列。
要与列进行比较的字符串值 必须使用与该列相同的排序规则
不直接支持联接;涉及多个表的条件查询 在可能的情况下被单独推送。使用扩展的EXPLAIN输出来确定哪些条件实际被下推。

参见"扩展EXPLAIN输出格式"。

以前,引擎条件下推仅限于引用条件被推送到的同一表中的列值的术语。

从NDB 8.0.16开始,查询计划早期表中的列值也可以从推送条件中引用。这减少了SQL节点在联接处理过程中必须处理的行数。

筛选也可以在LDM线程 中并行执行,而不是在单个mysqld进程中执行。

这有可能大大提高查询的性能。

从NDB 8.0.20开始,如果在同一联接嵌套中使用的 任何表上,或在其上面的联接嵌套中的任何表(它所依赖的)上不存在不可推送条件,则可以使用扫描推送外部联接半联接 也是如此,前提是所采用的优化策略是firstMatch

(请参阅"使用半联接转换优化IN和EXISTS子查询谓词")。

在以下两种情况下,联接算法不能与引用前一个表中的列相结合:

1.当前面引用的任何表都在联接缓冲区中时。在这种情况下,从扫描筛选表中检索的每一行都与缓冲区中的每一行都匹配。这意味着在生成扫描筛选器时,没有可以从中提取列值的特定行。

2.当列 源自被推送的join操作的子操作时。这是因为生成扫描筛选器时,尚未检索联接中原始表操作引用的行。

从NDB 8.0.27开始,联接原始表中的列可以向下推,前提是它们满足前面列出的要求。使用先前创建的表t1的这种查询的示例如下所示:

sql 复制代码
mysql> EXPLAIN 
    ->   SELECT * FROM t1 AS x 
    ->   LEFT JOIN t1 AS y 
    ->   ON x.a=0 AND y.b>=3\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: x
   partitions: p0,p1
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 4
     filtered: 100.00
        Extra: NULL
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: y
   partitions: p0,p1
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 4
     filtered: 100.00
        Extra: Using where; Using pushed condition (`test`.`y`.`b` >= 3); Using join buffer (hash join)
2 rows in set, 2 warnings (0.00 sec)
相关推荐
高兴就好(石1 小时前
DB-GPT部署和试用
数据库·gpt
这孩子叫逆1 小时前
6. 什么是MySQL的事务?如何在Java中使用Connection接口管理事务?
数据库·mysql
Karoku0662 小时前
【网站架构部署与优化】web服务与http协议
linux·运维·服务器·数据库·http·架构
码农郁郁久居人下2 小时前
Redis的配置与优化
数据库·redis·缓存
MuseLss3 小时前
Mycat搭建分库分表
数据库·mycat
Hsu_kk3 小时前
Redis 主从复制配置教程
数据库·redis·缓存
DieSnowK4 小时前
[Redis][环境配置]详细讲解
数据库·redis·分布式·缓存·环境配置·新手向·详细讲解
程序猿小D4 小时前
第二百三十五节 JPA教程 - JPA Lob列示例
java·数据库·windows·oracle·jdk·jpa
Flerken1014 小时前
数据库语言、SQL语言、数据库系统提供的两种语言
数据库·sql·oracle
掘根4 小时前
【网络】高级IO——poll版本TCP服务器
网络·数据库·sql·网络协议·tcp/ip·mysql·网络安全