下推到 TiKV 的表达式列表
当 TiDB 从 TiKV 中读取数据的时候,TiDB 会尽量下推一些表达式运算到 TiKV 中,从而减少数据传输量以及 TiDB 单一节点的计算压力。本文将介绍 TiDB 已支持下推的表达式,以及如何禁止下推特定表达式。
已支持下推的表达式列表
| 表达式分类 | 具体操作 | 
|---|---|
| 逻辑运算 | AND (&&), OR (||), NOT (!) | 
| 比较运算 | <, <=, =, != (<>), >, >=, <=>, IN(), IS NULL, LIKE, IS TRUE, IS FALSE, COALESCE() | 
| 数值运算 | +, -, *, /, ABS(), CEIL(), CEILING(), FLOOR(), MOD() | 
| 控制流运算 | CASE, IF(), IFNULL() | 
| JSON 运算 | JSON_TYPE(json_val), JSON_EXTRACT(json_doc, path[, path] ...), JSON_OBJECT(key, val[, key, val] ...), JSON_ARRAY([val[, val] ...]), JSON_MERGE(json_doc, json_doc[, json_doc] ...), JSON_SET(json_doc, path, val[, path, val] ...), JSON_INSERT(json_doc, path, val[, path, val] ...), JSON_REMOVE(json_doc, path[, path] ...)  | 
| 日期运算 | DATE_FORMAT(), SYSDATE() | 
| 字符串函数 | RIGHT() | 
禁止特定表达式下推
当已支持下推的表达式列表中的函数和运算符,或特定的数据类型(仅限 ENUM 类型 和 BIT 类型)的计算过程因下推而出现异常时,你可以使用黑名单功能禁止其下推,从而快速恢复 TiDB 业务。具体而言,你可以将函数名、运算符名,或数据列类型加入黑名单 mysql.expr_pushdown_blacklist 中,以禁止特定表达式下推。具体方法,请参阅加入黑名单。
mysql.expr_pushdown_blacklist 的 schema 如下:
tidb> desc mysql.expr_pushdown_blacklist;
+------------+--------------+------+------+-------------------+-------+
| Field      | Type         | Null | Key  | Default           | Extra |
+------------+--------------+------+------+-------------------+-------+
| name       | char(100)    | NO   |      | NULL              |       |
| store_type | char(100)    | NO   |      | tikv,tiflash,tidb |       |
| reason     | varchar(200) | YES  |      | NULL              |       |
+------------+--------------+------+------+-------------------+-------+
3 rows in set (0.00 sec)
以上结果字段解释如下:
name:禁止下推的函数名、运算符名或数据类型。store_type:用于指定希望禁止该函数、运算符或数据类型下推到哪些组件进行计算。组件可选tidb、tikv和tiflash。store_type不区分大小写,如果需要禁止向多个存储引擎下推,各个存储之间需用逗号隔开。store_type为tidb时表示在读取 TiDB 内存表时,是否允许该函数在其他 TiDB Server 上执行。store_type为tikv时表示是否允许该函数在 TiKV Server 的 Coprocessor 模块中执行。store_type为tiflash时表示是否允许该函数在 TiFlash Server 的 Coprocessor 模块中执行。
reason:用于记录该函数被加入黑名单的原因。
加入黑名单
执行以下步骤,可将一个或多函数名、运算符名或数据类型(仅限 ENUM 类型 和 BIT 类型)加入黑名单:
向
mysql.expr_pushdown_blacklist插入以下内容:- 希望禁止下推的函数名、运算符名或数据类型
 - 希望禁止下推的存储引擎
 
执行
admin reload expr_pushdown_blacklist;。
移出黑名单
执行以下步骤,可将一个或多个函数名、运算符名或数据类型移出黑名单:
- 从 
mysql.expr_pushdown_blacklist表中删除对应的函数名、运算符名或数据类型。 - 执行 
admin reload expr_pushdown_blacklist;。 
黑名单使用示例
以下示例首先将函数 DATE_FORMAT()、运算符 > 及 数据类型 BIT 加入黑名单,然后再将运算符 > 从黑名单中移出。
黑名单是否生效可以从 explain 结果中进行观察(参见如何理解 explain 结果)。
tidb> create table t(a int);
Query OK, 0 rows affected (0.06 sec)
tidb> explain select * from t where a < 2 and a > 2;
+-------------------------+----------+-----------+---------------+------------------------------------+
| id                      | estRows  | task      | access object | operator info                      |
+-------------------------+----------+-----------+---------------+------------------------------------+
| TableReader_7           | 0.00     | root      |               | data:Selection_6                   |
| └─Selection_6           | 0.00     | cop[tikv] |               | gt(ssb_1.t.a, 2), lt(ssb_1.t.a, 2) |
|   └─TableFullScan_5     | 10000.00 | cop[tikv] | table:t       | keep order:false, stats:pseudo     |
+-------------------------+----------+-----------+---------------+------------------------------------+
3 rows in set (0.00 sec)
tidb> insert into mysql.expr_pushdown_blacklist values('date_format()', 'tikv',''), ('>','tikv',''), ('bit','tikv','');
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0
tidb> admin reload expr_pushdown_blacklist;
Query OK, 0 rows affected (0.00 sec)
tidb> explain select * from t where a < 2 and a > 2;
+-------------------------+----------+-----------+---------------+------------------------------------+
| id                      | estRows  | task      | access object | operator info                      |
+-------------------------+----------+-----------+---------------+------------------------------------+
| Selection_7             | 10000.00 | root      |               | gt(ssb_1.t.a, 2), lt(ssb_1.t.a, 2) |
| └─TableReader_6         | 10000.00 | root      |               | data:TableFullScan_5               |
|   └─TableFullScan_5     | 10000.00 | cop[tikv] | table:t       | keep order:false, stats:pseudo     |
+-------------------------+----------+-----------+---------------+------------------------------------+
3 rows in set (0.00 sec)
tidb> delete from mysql.expr_pushdown_blacklist where name = '>';
Query OK, 1 row affected (0.01 sec)
tidb> admin reload expr_pushdown_blacklist;
Query OK, 0 rows affected (0.00 sec)
tidb> explain select * from t where a < 2 and a > 2;
+---------------------------+----------+-----------+---------------+--------------------------------+
| id                        | estRows  | task      | access object | operator info                  |
+---------------------------+----------+-----------+---------------+--------------------------------+
| Selection_8               | 0.00     | root      |               | lt(ssb_1.t.a, 2)               |
| └─TableReader_7           | 0.00     | root      |               | data:Selection_6               |
|   └─Selection_6           | 0.00     | cop[tikv] |               | gt(ssb_1.t.a, 2)               |
|     └─TableFullScan_5     | 10000.00 | cop[tikv] | table:t       | keep order:false, stats:pseudo |
+---------------------------+----------+-----------+---------------+--------------------------------+
4 rows in set (0.00 sec)
| 运算符原始名称 | 运算符别名 | 
|---|---|
| < | lt | 
| > | gt | 
| <= | le | 
| >= | ge | 
| = | eq | 
| != | ne | 
<> | ne | 
<=> | nulleq | 
| | | bitor | 
| && | bitand | 
| || | or | 
| ! | not | 
| in | in | 
| + | plus | 
| - | minus | 
| * | mul | 
| / | div | 
| DIV | intdiv | 
| IS NULL | isnull | 
| IS TRUE | istrue | 
| IS FALSE | isfalse |