【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)
相关推荐
AI军哥25 分钟前
MySQL8的安装方法
人工智能·mysql·yolo·机器学习·deepseek
小光学长42 分钟前
基于vue框架的电信用户业务管理系统的设计与实现8ly70(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库
程序员不想YY啊1 小时前
MySQL元数据库完全指南:探秘数据背后的数据
数据库·mysql·oracle
数据最前线1 小时前
Doris表设计与分区策略:让海量数据管理更高效
数据库
时光追逐者1 小时前
MongoDB从入门到实战之MongoDB快速入门(附带学习路线图)
数据库·学习·mongodb
头顶秃成一缕光2 小时前
Redis的主从模式和哨兵模式
数据库·redis·缓存
AIGC大时代2 小时前
高效使用DeepSeek对“情境+ 对象 +问题“型课题进行开题!
数据库·人工智能·算法·aigc·智能写作·deepseek
博睿谷IT99_2 小时前
数据库证书可以选OCP认证吗?
数据库·oracle·开闭原则·ocp认证
乐维_lwops2 小时前
数据库监控 | MongoDB监控全解析
数据库·mongodb·数据库监控
观无2 小时前
Redis安装及入门应用
数据库·redis·缓存