Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 Reference Manual  /  ...  /  Engine Condition Pushdown Optimization

10.2.1.5 引擎条件下推优化

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

对于 NDB 集群,这个优化可以消除在数据节点和 MySQL 服务器之间传输不匹配行的需要,并且可以加速查询,提高速度5到10倍于不使用条件下推的情况。

假设一个 NDB 集群表定义如下:

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上的索引(索引访问方法更高效,因此将被选择而不是条件下推)。

引擎条件下推也可以在使用>或<操作符比较带有索引列和常量时使用:

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 必须是一个字符串字面量,用于匹配的模式;语法请见第14.8.1节,“字符串比较函数和操作符”

  • column IS [NOT] NULL

  • column IN (value_list)

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

  • column BETWEEN constant1 AND constant2

    constant1constant2 都必须是一个常量字面值。

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

引擎条件推送是默认启用的。要在服务器启动时禁用它,请将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.4 中,列可以相互比较,只要它们的类型相同,包括同样的有符号、长度、字符集、精度和小数点位数,其中适用时。

  • 用于比较的列不能是BLOBTEXTJSONBITENUM 列。

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

  • 不支持直接连接;涉及多个表的条件下推单独进行,可能情况下推。使用扩展EXPLAIN 输出来确定实际下推了哪些条件。见第10.8.3节,“扩展 EXPLAIN 输出格式”

之前,引擎条件下推只能引用同一个表中的列值。在 NDB 8.4 中,可以从查询计划中的前面表中引用列值。这减少了 SQL 节点在连接处理期间需要处理的行数。可以并行在 LDM 线程中执行过滤,而不是在单个 mysqld 进程中。这可能会提高查询的性能。

NDB 可以使用扫描推送外连接,如果在同一个连接nest中没有任何不可下推条件,或者它依赖的连接nest中的任何表上没有不可下推条件。这也适用于半连接,假设使用的是 firstMatch 优化策略(见Optimizing IN and EXISTS Subquery Predicates with Semijoin Transformations)。

连接算法不能与之前表中的引用列结合在一起的情况:

  1. 当任何被引用的前面表位于连接缓冲区中。在这种情况下,每个从扫描过滤表中检索的行都将与缓冲区中的每一行进行匹配。这意味着,在生成扫描过滤时,不能从单个特定的行中获取列值。

  2. 当列来自推送连接的子操作。在这种情况下,来自祖先操作的行还没有被检索出来,当扫描过滤被生成时。

祖先表中的列可以被推下,假设它们满足之前列出的要求。使用之前创建的表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)