为提高效率,请提供以下信息,问题描述清晰能够更快得到解决:
【 TiDB 使用环境】
TiDB v4.0.13测试环境
【概述】 场景 + 问题概述
最近在看SQL优化相关的文档,发现有列裁剪这一优化
假设表 t 里面有 a b c d 四列,执行如下语句:
select a from t where b > 5
在该查询的过程中,t 表实际上只有 a, b 两列会被用到,而 c, d 的数据则显得多余。对应到该语句的查询计划,Selection 算子会用到 b 列,下面接着的 DataSource 算子会用到 a, b 两列,而剩下 c, d 两列则都可以裁剪掉,DataSource 算子在读数据时不需要将它们读进来。
出于上述考量,TiDB 会在逻辑优化阶段进行自上而下的扫描,裁剪不需要的列,减少资源浪费。该扫描过程称作 “列裁剪”,对应逻辑优化规则中的 columnPruner
。如果要关闭这个规则,可以在参照优化规则及表达式下推的黑名单中的关闭方法。
【背景】 做过哪些操作
关闭列裁剪前的执行计划
(root@127.0.0.1:4000) [tidb_test] show create table tab_tidb;
+----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tab_tidb | CREATE TABLE `tab_tidb` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL DEFAULT '',
`age` int(11) NOT NULL DEFAULT '0',
`version` varchar(20) NOT NULL DEFAULT '',
`status` int(11) DEFAULT '1',
PRIMARY KEY (`id`),
KEY `idx_age` (`age`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=150002 |
+----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)
(root@127.0.0.1:4000) [tidb_test] explain select name from tab_tidb where id >2;
+--------------------------+---------+-----------+----------------+----------------------------------+
| id | estRows | task | access object | operator info |
+--------------------------+---------+-----------+----------------+----------------------------------+
| Projection_4 | 2.00 | root | | tidb_test.tab_tidb.name |
| └─TableReader_6 | 2.00 | root | | data:TableRangeScan_5 |
| └─TableRangeScan_5 | 2.00 | cop[tikv] | table:tab_tidb | range:(2,+inf], keep order:false |
+--------------------------+---------+-----------+----------------+----------------------------------+
3 rows in set (0.04 sec)
关闭列裁剪
(root@127.0.0.1:4000) [tidb_test] select * from mysql.opt_rule_blacklist;
Empty set (0.01 sec)
(root@127.0.0.1:4000) [tidb_test] INSERT INTO mysql.opt_rule_blacklist VALUES("column_prune");
Query OK, 1 row affected (0.07 sec)
(root@127.0.0.1:4000) [tidb_test] ADMIN reload opt_rule_blacklist;
Query OK, 0 rows affected (0.01 sec)
(root@127.0.0.1:4000) [tidb_test] select * from mysql.opt_rule_blacklist;
+--------------+
| name |
+--------------+
| column_prune |
+--------------+
1 row in set (0.01 sec)
关闭列裁剪后的执行计划
(root@127.0.0.1:4000) [tidb_test] explain select name from tab_tidb where id >2;
+--------------------------+---------+-----------+----------------+----------------------------------+
| id | estRows | task | access object | operator info |
+--------------------------+---------+-----------+----------------+----------------------------------+
| Projection_4 | 2.00 | root | | tidb_test.tab_tidb.name |
| └─TableReader_6 | 2.00 | root | | data:TableRangeScan_5 |
| └─TableRangeScan_5 | 2.00 | cop[tikv] | table:tab_tidb | range:(2,+inf], keep order:false |
+--------------------------+---------+-----------+----------------+----------------------------------+
3 rows in set (0.01 sec)
发现执行计划并木有变化,难道是TiDB内部的优化,从执行计划上看不出来?