为什么语句的执行计划没有算子

版本:v6.5.3
数据来源于tpch
语句:

explain analyze select * from  orders where O_ORDERKEY >=(select O_ORDERKEY  from  orders where O_TOTALPRICE >=370000 order by O_ORDERDATE asc limit 500,1)   limit 10;
表结构
mysql> show create table orders;
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table  | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| orders | CREATE TABLE `orders` (
  `O_ORDERKEY` bigint(20) NOT NULL,
  `O_CUSTKEY` bigint(20) NOT NULL,
  `O_ORDERSTATUS` char(1) NOT NULL,
  `O_TOTALPRICE` decimal(15,2) NOT NULL,
  `O_ORDERDATE` date NOT NULL,
  `O_ORDERPRIORITY` char(15) NOT NULL,
  `O_CLERK` char(15) NOT NULL,
  `O_SHIPPRIORITY` bigint(20) NOT NULL,
  `O_COMMENT` varchar(79) NOT NULL,
  PRIMARY KEY (`O_ORDERKEY`) /*T![clustered_index] CLUSTERED */,
  KEY `index_O_TOTALPRICE` (`O_TOTALPRICE`),
  KEY `index_a` (`O_ORDERSTATUS`,`O_TOTALPRICE`),
  KEY `indexO_CUSTKEY` (`O_CUSTKEY`),
  KEY `index_date` (`O_ORDERDATE`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin |

在此处键入或粘贴代码

执行计划

mysql> explain analyze select * from  orders where O_ORDERKEY >=(select O_ORDERKEY  from  orders where O_TOTALPRICE >=370000 order by O_ORDERDATE asc limit 500,1)   limit 10;
+---------------------------+---------+---------+-----------+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------+---------+------+
| id                        | estRows | actRows | task      | access object | execution info                                                                                                                                                                                                    | operator info                          | memory  | disk |
+---------------------------+---------+---------+-----------+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------+---------+------+
| Limit_31                  | 10.00   | 10      | root      |               | time:2.19ms, loops:2                                                                                                                                                                                              | offset:0, count:10                     | N/A     | N/A  |
| └─TableReader_34          | 10.00   | 32      | root      |               | time:2.19ms, loops:1, cop_task: {num: 1, max: 2.07ms, proc_keys: 224, rpc_num: 1, rpc_time: 2.04ms, copr_cache: disabled, distsql_concurrency: 15}                                                                | data:TableRangeScan_33                 | 39.3 KB | N/A  |
|   └─TableRangeScan_33     | 10.00   | 224     | cop[tikv] | table:orders  | tikv_task:{time:0s, loops:3}, scan_detail: {total_process_keys: 224, total_process_keys_size: 33960, total_keys: 225, get_snapshot_time: 20.2µs, rocksdb: {key_skipped_count: 224, block: {cache_hit_count: 7}}}  | range:[2980966,+inf], keep order:false | N/A     | N/A  |
+---------------------------+---------+---------+-----------+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------+---------+------+
3 rows in set (0.11 sec)

有个比较好奇的点,为什么执行计划没有sort 算子?

子查询预处理掉了吧

然后后边走了limit

老师 能详细解释下嘛

看看select O_ORDERKEY from orders where O_TOTALPRICE >=370000 order by O_ORDERDATE asc limit 500,1执行计划,应该是执行计划不完整

可以参考我遇到的tidb执行计划不全的问题

有没有可能是因为o_orderdate本身有索引,就是已排好序了,再引用limit就不需要排序了?直接到索引查就可以了,所以不显示sort

根据执行计划推断,大概率是优化器经过优化后,发现不需要排序也可以满足SQL的查询需求。考虑到底层存储数据是是按key 有序排列的,本身数据就有排序特征,不用通过执行sort 算子拿到有序数据也是有可能的。

1.为啥执行计划没出现子查询里面相关步骤,因为在优化阶段提前执行了,参考:
https://docs.pingcap.com/zh/tidb/stable/subquery-optimization#exists-子查询以及---select--from-

所以子查询里面可能有排序,但是也看不到

2.为啥外层查询执行计划没有出现排序,因为外层查询本身没有排序,只需要随便取10条就好了

2 个赞

楼上说的对,应该是预处理了。

子查询直接给优化掉了

O_ORDERKEY 主键。聚集索引,还有比走他更快的吗?不需要排序了

O_ORDERKEY 是主键,是已经排序过了,不需要再排序

执行计划展示还是需要改进,即便是括号内子查询被提前执行获得一个常量,但应该也在执行计划中展示出来,或者单独一个算子说明子查询的执行情况:是否全表、走了哪个索引 这些也是需要展示的,否则不知道这部分咋执行的

offset:0, count:10
data:TableRangeScan_33
range:[2980966,+inf], keep order:false
这应该是没执行完成吧?

大佬 说的对

对的 我也认为应该执行计划展现下,否则太不清晰了

此话题已在最后回复的 60 天后被自动关闭。不再允许新回复。