下推到 TiKV 的表达式列表

当 TiDB 从 TiKV 中读取数据的时候,TiDB 会尽量下推一些表达式运算到 TiKV 中,从而减少数据传输量以及 TiDB 单一节点的计算压力。本文将介绍 TiDB 已支持下推的表达式,以及如何禁止下推特定表达式。

已支持下推的表达式列表

表达式分类 具体操作
逻辑运算 AND (&&), OR (||), NOT (!)
比较运算 <, <=, =, != (<>), >, >=, <=>, IN(), IS NULL, LIKE, IS TRUE, IS FALSE, COALESCE()
数值运算 +, -, *, /, ABS(), CEIL(), CEILING(), FLOOR()
控制流运算 CASE, IF(), IFNULL()
JSON运算 JSON_TYPE(json_val),
JSON_EXTRACT(json_doc, path[, path] …),
JSON_UNQUOTE(json_val),
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_REPLACE(json_doc, path, val[, path, val] …),
JSON_REMOVE(json_doc, path[, path] …)
日期运算 DATE_FORMAT()

禁止特定表达式下推

当函数的计算过程由于下推而出现异常时,可通过黑名单功能禁止其下推来快速恢复业务。具体而言,你可以将上述支持的函数或运算符名加入黑名单 mysql.expr_pushdown_blacklist 中,以禁止特定表达式下推。

加入黑名单

执行以下步骤,可将一个或多个函数或运算符加入黑名单:

  1. mysql.expr_pushdown_blacklist 插入对应的函数名或运算符名。
  2. 执行 admin reload expr_pushdown_blacklist;

移出黑名单

执行以下步骤,可将一个或多个函数及运算符移出黑名单:

  1. mysql.expr_pushdown_blacklist 表中删除对应的函数名或运算符名。
  2. 执行 admin reload expr_pushdown_blacklist;

黑名单用法示例

以下示例首先将运算符 <> 加入黑名单,然后将运算符 > 从黑名单中移出。

黑名单是否生效可以从 explain 结果中进行观察(参见如何理解 explain 结果)。

  1. tidb> create table t(a int);
  2. Query OK, 0 rows affected (0.01 sec)
  3. tidb> explain select * from t where a < 2 and a > 2;
  4. +---------------------+----------+------+------------------------------------------------------------+
  5. | id | count | task | operator info |
  6. +---------------------+----------+------+------------------------------------------------------------+
  7. | TableReader_7 | 0.00 | root | data:Selection_6 |
  8. | └─Selection_6 | 0.00 | cop | gt(test.t.a, 2), lt(test.t.a, 2) |
  9. | └─TableScan_5 | 10000.00 | cop | table:t, range:[-inf,+inf], keep order:false, stats:pseudo |
  10. +---------------------+----------+------+------------------------------------------------------------+
  11. 3 rows in set (0.00 sec)
  12. tidb> insert into mysql.expr_pushdown_blacklist values('<'), ('>');
  13. Query OK, 2 rows affected (0.00 sec)
  14. Records: 2 Duplicates: 0 Warnings: 0
  15. tidb> admin reload expr_pushdown_blacklist;
  16. Query OK, 0 rows affected (0.00 sec)
  17. tidb> explain select * from t where a < 2 and a > 2;
  18. +---------------------+----------+------+------------------------------------------------------------+
  19. | id | count | task | operator info |
  20. +---------------------+----------+------+------------------------------------------------------------+
  21. | Selection_5 | 8000.00 | root | gt(test.t.a, 2), lt(test.t.a, 2) |
  22. | └─TableReader_7 | 10000.00 | root | data:TableScan_6 |
  23. | └─TableScan_6 | 10000.00 | cop | table:t, range:[-inf,+inf], keep order:false, stats:pseudo |
  24. +---------------------+----------+------+------------------------------------------------------------+
  25. 3 rows in set (0.00 sec)
  26. tidb> delete from mysql.expr_pushdown_blacklist where name = '>';
  27. Query OK, 1 row affected (0.00 sec)
  28. tidb> admin reload expr_pushdown_blacklist;
  29. Query OK, 0 rows affected (0.00 sec)
  30. tidb> explain select * from t where a < 2 and a > 2;
  31. +-----------------------+----------+------+------------------------------------------------------------+
  32. | id | count | task | operator info |
  33. +-----------------------+----------+------+------------------------------------------------------------+
  34. | Selection_5 | 2666.67 | root | lt(test.t.a, 2) |
  35. | └─TableReader_8 | 3333.33 | root | data:Selection_7 |
  36. | └─Selection_7 | 3333.33 | cop | gt(test.t.a, 2) |
  37. | └─TableScan_6 | 10000.00 | cop | table:t, range:[-inf,+inf], keep order:false, stats:pseudo |
  38. +-----------------------+----------+------+------------------------------------------------------------+
  39. 4 rows in set (0.00 sec)

注意:

  • admin reload expr_pushdown_blacklist 只对执行该 SQL 语句的 TiDB server 生效。若需要集群中所有 TiDB server 生效,需要在每台 TiDB server 上执行该 SQL 语句。
  • 表达式黑名单功能在 v3.0.0 及以上版本中支持。
  • 在 v3.0.3 及以下版本中,不支持将某些运算符的原始名称文本(如 “>”、”+” 和 “is null”)加入黑名单中,部分运算符在黑名单中需使用别名。已支持下推的表达式中,别名与原始名不同的运算符见下表(区分大小写)。
运算符原始名称 运算符别名
< 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