Documentation Home
MySQL 8.0 参考手册  / 第8章优化  / 8.2 优化SQL语句  / 8.2.1 优化 SELECT 语句  /  8.2.1.5 发动机工况下推优化

8.2.1.5 发动机工况下推优化

这种优化提高了非索引列和常量之间直接比较的效率。在这种情况下,条件被下推到存储引擎进行评估。此优化只能由NDB存储引擎使用。

对于 NDB Cluster,这种优化可以消除在集群的数据节点和发出查询的 MySQL 服务器之间通过网络发送非匹配行的需要,并且可以在使用它的情况下加快查询速度 5 到 10 倍条件下推可以但未使用的地方。

假设 NDB Cluster 表定义如下:

CREATE TABLE t1 (
    a INT,
    b INT,
    KEY(a)
) ENGINE=NDB;

引擎条件下推可用于查询,例如此处显示的查询,其中包括非索引列和常量之间的比较:

SELECT a, b FROM t1 WHERE b = 10;

引擎条件下推的使用可以在以下输出中看到EXPLAIN

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

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

SELECT a,b FROM t1 WHERE a = 10;

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

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

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] LIKE pattern

    pattern必须是包含要匹配的模式的字符串文字;有关语法,请参阅第 12.8.1 节,“字符串比较函数和运算符”

  • column IS [NOT] NULL

  • column IN (value_list)

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

  • column BETWEEN constant1 AND constant2

    constant1并且 constant2每个都必须是常量,文字值。

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

默认情况下启用引擎状态下推。要在服务器启动时禁用它,请将 optimizer_switch系统变量的 engine_condition_pushdown 标志设置为off。例如,在一个 my.cnf文件中,使用这些行:

[mysqld]
optimizer_switch=engine_condition_pushdown=off

在运行时,像这样禁用条件下推:

SET optimizer_switch='engine_condition_pushdown=off';

限制。  发动机状态下推受以下限制:

  • 只有 NDB存储引擎支持引擎条件下推。

  • 在 NDB 8.0.18 之前,列可以与仅计算为常量值的常量或表达式进行比较。在 NDB 8.0.18 及更高版本中,只要列的类型完全相同,包括相同的符号、长度、字符集、精度和小数位数,它们就可以相互比较。

  • 比较中使用的列不能是 BLOBTEXT类型中的任何一种。此排除也扩展到JSONBITENUM列。

  • 要与列进行比较的字符串值必须使用与该列相同的排序规则。

  • 不直接支持连接;涉及多个表的条件在可能的情况下被单独推送。使用扩展EXPLAIN输出来确定实际下推哪些条件。请参阅 第 8.8.3 节,“扩展 EXPLAIN 输出格式”

以前,引擎条件下推仅限于引用条件被推送到的同一表中的列值的术语。从 NDB 8.0.16 开始,查询计划中早期表中的列值也可以从推送条件中引用。这减少了连接处理期间必须由 SQL 节点处理的行数。过滤也可以在 LDM 线程中并行执行,而不是在单个mysqld 进程中执行。这有可能显着提高查询的性能。

从 NDB 8.0.20 开始,如果在同一连接嵌套中使用的任何表或它所依赖的连接嵌套中的任何表上没有不可推送的条件,则可以推送使用扫描的外部连接。如果采用的优化策略是 firstMatch(请参阅 第 8.2.2.1 节,“使用半连接转换优化 IN 和 EXISTS 子查询谓词”),这对于半连接也是如此。

在以下两种情况下,连接算法不能与先前表中的引用列结合使用:

  1. 当任何引用的先前表在连接缓冲区中时。在这种情况下,从扫描过滤表中检索的每一行都与缓冲区中的每一行相匹配。这意味着在生成扫描过滤器时,没有可以从中获取列值的单个特定行。

  2. 当列源自推送连接中的子操作时。这是因为在生成扫描过滤器时,尚未检索从联接中的祖先操作引用的行。

从 NDB 8.0.27 开始,可以下推连接中祖先表中的列,前提是它们满足前面列出的要求。t1此处显示了使用先前创建 的表的此类查询的示例:

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)