该优化可以提高非索引列与常量之间的直接比较效率。在这种情况下,条件将被“推送”到存储引擎中进行评估。该优化只能由 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] LIKEpattern
pattern
必须是一个字符串文字,包含要匹配的模式;语法见 第 14.8.1 节,“字符串比较函数和运算符”。 -
column
IS [NOT] NULL -
column
IN (value_list
)每个
value_list
项必须是一个常量,文字值。 -
column
BETWEENconstant1
ANDconstant2
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 8.3 中,可以从查询计划中的早期表引用的列值也可以被推送。这减少了 SQL 节点在连接处理期间需要处理的行数。过滤也可以在 LDM 线程中并行执行,而不是在单个mysqld进程中。这可能会大幅提高查询性能。
NDB
可以推送使用扫描的外连接,如果没有不可推送的条件在任何表上,或者在其依赖的任何表上,也可以推送半连接,前提是优化策略是 firstMatch
(见使用半连接转换优化 IN 和 EXISTS 子查询谓词)。
连接算法不能与之前表的引用的列组合在以下两种情况下:
-
当任何前一个表在连接缓冲区中时。在这种情况下,从扫描过滤表中检索的每一行都将与缓冲区中的每一行匹配。这意味着在生成扫描过滤器时,无法从单个特定行中获取列值。
-
当列来自连接中的子操作时。这是因为在生成扫描过滤器时,祖先操作中的行还没有被检索。
在连接中,祖先表中的列可以被推送到底,只要它们满足之前列出的要求。使用之前创建的表 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)