这种优化提高了非索引列和常量之间直接比较的效率。在这种情况下,条件被“ 下推 ”到存储引擎进行评估。此优化只能由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;
条件下推不适用于此处,因为column上存在索引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
条件下推的其他受支持的比较包括:
1、column [NOT] LIKE pattern
2、pattern必须是包含要匹配的模式的字符串文字;有关语法,请参见第12.7.1节“字符串比较函数和运算符”。
3、column IS [NOT] NULL
4、column IN (value_list)
5、中的每个项目都value_list 必须是恒定的文字值。
6、column BETWEEN constant1 AND constant2
7、constant1并且 constant2每个值都必须是恒定的文字值。
在上述列表中的所有情况下,都有可能将条件转换为列与常量之间的一个或多个直接比较的形式。
默认情况下,引擎状态下推处于启用状态。要在服务器启动时禁用它,请设置 optimizer_switch系统变量。例如,在my.cnf文件中,使用以下几行:
[mysqld]
optimizer_switch=engine_condition_pushdown=off
在运行时,禁用条件下推,如下所示:
SET optimizer_switch='engine_condition_pushdown=off';
局限性。 引擎状态下推受以下限制:
1、条件下推仅受NDB存储引擎支持 。
2、在NDB 8.0.18之前,可以将列与仅求常数值的常数或表达式进行比较。在NDB 8.0.18及更高版本中,只要适用于相同类型的列(包括相同的符号,长度,字符集,精度和小数位数),它们就可以相互比较。
3、比较中使用的列不能为 BLOB或 TEXT类型。此排除范围也扩展到JSON, BIT和 ENUM列。
4、要与列进行比较的字符串值必须使用与列相同的排序规则。
5、不直接支持联接;涉及多个表的条件将在可能的情况下分别推送。使用扩展EXPLAIN输出来确定实际按下了哪些条件。请参见 第8.8.3节“扩展的EXPLAIN输出格式”。
以前,条件下推仅限于引用条件被推到的同一表中列值的术语。从NDB 8.0.16开始,查询计划中较早的表中的列值也可以从推送条件中引用。这减少了连接处理期间SQL节点必须处理的行数。过滤也可以在LDM线程中并行执行,而不是在单个mysqld 进程中执行。这有可能极大地提高查询性能。
从NDB 8.0.20开始,如果在同一联接嵌套中使用的任何表或它所依赖的联接nmest中的任何表上没有不可推动的条件,则可以推送使用扫描的外部联接。如果使用了优化策略,则对于半连接也是如此firstMatch(请参见 第8.2.2.1节“使用半连接 转换优化IN和EXISTS子查询谓词”)。
在以下两种情况下,联接算法不能与先前表中的引用列结合使用:
1、当任何引用的先前表在连接缓冲区中时。在这种情况下,将从扫描筛选表中检索的每一行与缓冲区中的每一行进行匹配。这意味着在生成扫描过滤器时,没有单个特定的行可以从中获取列值。
2、当该列源自推送连接中的子操作时。这是因为生成扫描过滤器时,尚未检索到联接中祖先操作引用的行。