#### 8.2.1.5发动机工况下推优化

[](<>)[](<>)

这种优化提高了无索引柱和常数之间直接比较的效率。在这种情况下，条件被“下推”到存储引擎进行评估。此优化只能由[`NDB`](mysql-cluster.html)存储引擎。

对于NDB集群，这种优化可以消除在集群的数据节点和发出查询的MySQL服务器之间通过网络发送不匹配行的需要，并且可以在使用条件下推的情况下将查询速度提高5到10倍。

假设NDB集群表定义如下：

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

Engine condition pushdown可用于如下所示的查询，其中包括非索引列和常量之间的比较：

```
SELECT a, b FROM t1 WHERE b = 10;
```

发动机工况下推的使用可以从发动机的输出中看出[`解释`](explain.html):

```
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
```

其他支持的发动机工况下推比较包括：

-   `*`柱`*[不是]像*`图案`*`

    *`图案`*必须是包含要匹配的模式的字符串文字；有关语法，请参阅[第12.8.1节，“字符串比较函数和运算符”](string-comparison-functions.html).

-   `*`柱`*是[不是]空的`

-   `*`柱`*在(*`价值清单`*)`

    表中的每一项*`价值清单`*必须是常量、文字值。

-   `*`柱`*中间*`康斯坦特1`*及*`康斯坦斯2`*`

     *`康斯坦特1`*和*`康斯坦斯2`*每个都必须是一个常量、文字值。

    在上述列表中的所有情况下，条件都可以转换为列和常量之间的一个或多个直接比较形式。

    默认情况下启用“发动机状况下推”。要在服务器启动时禁用它，请设置[`优化器_开关`](server-system-variables.html#sysvar_optimizer_switch)系统变量[`发动机状况下推`](switchable-optimizations.html#optflag_engine-condition-pushdown)向`关`.例如，在`我的cnf`文件中，使用以下行：


```
[mysqld]
optimizer_switch=engine_condition_pushdown=off
```

在运行时，禁用条件下推，如下所示：

```
SET optimizer_switch='engine_condition_pushdown=off';
```

**局限性**发动机工况下推受到以下限制：

-   发动机状况下推仅由[`NDB`](mysql-cluster.html)存储引擎。

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

-   比较中使用的列不能是以下任何一种[`斑点`](blob.html)或[`文本`](blob.html)类型。这种排除适用于[`JSON`](json.html), [`一点`](bit-type.html)和[`枚举`](enum.html)专栏也是如此。

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

-   不直接支持联接；在可能的情况下，涉及多个表的条件会被单独推送。使用扩展[`解释`](explain.html)输出以确定实际按下的条件。看见[第8.8.3节，“扩展解释输出格式”](explain-extended.html).

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

    从NDB 8.0.20开始，如果在同一联接嵌套中使用的任何表上，或者在其依赖的联接嵌套上的任何表上，没有不可推送的条件，则可以推送使用扫描的外部联接。如果采用的优化策略是`第一场比赛`（见[第8.2.2.1节，“使用半连接转换优化IN和EXISTS子查询谓词”](semijoins.html)).

    在以下两种情况下，联接算法不能与前面表中的引用列组合使用：

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)
```
