优化规则黑名单与表达式下推
本文介绍如何使用优化规则黑名单和表达式下推黑名单来控制 TiDB 的行为。
优化规则黑名单
优化规则黑名单是一种调优优化规则的方法,主要用于手动禁用某些优化规则。
重要的优化规则
优化规则 | 规则名称 | 描述 |
---|---|---|
列裁剪 | column_prune | 如果上层执行器不需要某列,则会裁剪该列。 |
去相关子查询 | decorrelate | 尝试将相关子查询重写为非相关的连接或聚合。 |
聚合消除 | aggregation_eliminate | 尝试从执行计划中移除不必要的聚合操作符。 |
投影消除 | projection_eliminate | 移除执行计划中不必要的投影操作符。 |
Max/Min 消除 | max_min_eliminate | 将某些 Max/Min 函数重写为 order by + limit 1 形式。 |
predicate 下推 | predicate_push_down | 尝试将谓词下推到更接近数据源的操作符。 |
外连接消除 | outer_join_eliminate | 尝试移除执行计划中不必要的左连接或右连接。 |
分区裁剪 | partition_processor | 裁剪被谓词拒绝的分区,并将分区表查询重写为 UnionAll + Partition Datasource 形式。 |
聚合下推 | aggregation_push_down | 尝试将聚合操作下推到其子节点。 |
TopN 下推 | topn_push_down | 尝试将 TopN 操作符下推到更接近数据源的位置。 |
连接重排序 | join_reorder | 决定多表连接的执行顺序。 |
从窗口函数派生 TopN 或 Limit | derive_topn_from_window | 从窗口函数中派生出 TopN 或 Limit 操作符。 |
禁用优化规则
你可以使用优化规则黑名单禁用某些规则,以避免某些规则导致的特殊查询执行计划不理想。
使用方法
如果你想禁用某些规则,可以将其名称写入
mysql.opt_rule_blacklist
表。例如:INSERT INTO mysql.opt_rule_blacklist VALUES("join_reorder"), ("topn_push_down");执行以下 SQL 语句可以立即生效。生效范围包括所有旧连接的 TiDB 实例:
admin reload opt_rule_blacklist;如果想重新启用某个规则,可以删除对应的表中的数据,然后运行
admin reload
语句:DELETE FROM mysql.opt_rule_blacklist WHERE name IN ("join_reorder", "topn_push_down");admin reload opt_rule_blacklist;
表达式下推黑名单
表达式下推黑名单是一种调优表达式下推的方法,主要用于手动禁用某些特定数据类型的表达式。
支持下推的表达式
关于支持下推到 TiKV 的表达式的详细信息,请参见 Supported expressions for pushdown to TiKV。
禁用特定表达式的下推
当因表达式下推导致结果错误时,你可以使用黑名单快速恢复应用的正确性。具体来说,可以将部分支持的函数或操作符添加到 mysql.expr_pushdown_blacklist
表中,以禁用特定表达式的下推。
mysql.expr_pushdown_blacklist
表的结构如下:
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 服务器上执行该函数。 - 当
store_type
为tikv
时,表示是否允许在 TiKV 服务器的 Coprocessor 组件中执行该函数。 - 当
store_type
为tiflash
时,表示是否允许在 TiFlash 服务器的 Coprocessor 组件中执行该函数。
- 当
reason
:记录将该函数加入黑名单的原因。
使用方法
本节介绍如何使用表达式下推黑名单。
添加到黑名单
将一个或多个表达式(函数或操作符)加入黑名单,步骤如下:
将对应的函数名或操作符名,以及你希望禁用下推的组件集,插入到
mysql.expr_pushdown_blacklist
表中。执行
admin reload expr_pushdown_blacklist
。
从黑名单中移除
将一个或多个表达式从黑名单中移除,步骤如下:
从
mysql.expr_pushdown_blacklist
表中删除对应的函数名或操作符名,以及你希望禁用下推的组件集。执行
admin reload expr_pushdown_blacklist
。
表达式黑名单使用示例
以下示例中,将 <
和 >
操作符加入黑名单,然后将 >
操作符从黑名单中移除。
为了判断黑名单是否生效,可以观察 EXPLAIN
的结果(详见 TiDB 查询执行计划概述)。
以下 SQL 语句的
WHERE
子句中的谓词a < 2
和a > 2
可以被下推到 TiKV。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)将表达式插入到
mysql.expr_pushdown_blacklist
表中,并执行admin reload expr_pushdown_blacklist
。INSERT INTO mysql.expr_pushdown_blacklist VALUES('<','tikv',''), ('>','tikv','');Query OK, 2 rows affected (0.01 sec) Records: 2 Duplicates: 0 Warnings: 0admin reload expr_pushdown_blacklist;Query OK, 0 rows affected (0.00 sec)再次观察执行计划,发现
<
和>
操作符都没有被下推到 TiKV Coprocessor。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)从黑名单中移除一个表达式(这里是
>
),并执行admin reload expr_pushdown_blacklist
。DELETE FROM mysql.expr_pushdown_blacklist WHERE name = '>';Query OK, 1 row affected (0.01 sec)admin reload expr_pushdown_blacklist;Query OK, 0 rows affected (0.00 sec)再次观察执行计划,发现
<
不被下推,而>
被下推到 TiKV Coprocessor。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 | +---------------------------+----------+-----------+---------------+--------------------------------+