Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

MySQL 8.3 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.3 中,列可以相互比较,只要它们具有相同的类型,包括相同的符号、长度、字符集、精度和比例,其中这些是适用的。

  • 用于比较的列不能是BLOBTEXT类型。这也排除了JSONBITENUM列。

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

  • 连接不直接支持;多个表的条件将被单独推送。使用扩展的EXPLAIN输出来确定哪些条件实际被推送。见第 10.8.3 节,“扩展 EXPLAIN 输出格式”

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

NDB 可以推送使用扫描的外连接,如果没有不可推送的条件在任何表上,或者在其依赖的任何表上,也可以推送半连接,前提是优化策略是 firstMatch(见使用半连接转换优化 IN 和 EXISTS 子查询谓词)。

连接算法不能与之前表的引用的列组合在以下两种情况下:

  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)