执行计划问题-Index Lookup Join效率低下

【 TiDB 使用环境】调研
【 TiDB 版本】6.2
【遇到的问题】做主键的Index Lookup Join时效率低下
【问题现象及影响】

执行计划问题.txt (13.1 KB)

我在模拟Index Lookup Join观察执行效率时发现在读取内表数据时效率特别低(故意关闭了tidb端的缓存,多次重复执行后都是大约2秒左右)。
如附件中执行计划1所示内表是用主键C_CUSTKEY来做关联,在算子TableReader_56(Probe)中看到最大的一次cop_task任务需要363.3ms,max_proc_keys: 636 (通过total_process_keys: 6196,total_keys: 6200可以推测出max_keys也不会超过640),也就是扫描636个key而且都是内存读(block: {cache_hit_count: 24023},可以认定没有发生物理读),为何需要这么高的时间呢?
为了做对比模拟,直接单独查询customer表的主键C_CUSTKEY,模拟全内存读,扫描记录数大于640(这里设置为1000),反复多次试验找花费时间最久的一次,如附件执行计划2所示,可以看出tikv扫描total_process_keys: 999时几乎不花费时间。
所以请教下,记录数不大的关联,走主键索引的情况下还会出现这么慢的情况?

补充trace执行情况:
trace执行时间.txt (25.0 KB)

单看外表通过索引过滤的查询也是慢:select count(O_CUSTKEY) from orders b where b.O_ORDERDATE =‘1996-12-14’ 实际结果才6k多,但需要花费1秒多。
具体数据见附件:orders拆步单表查下慢数据.txt (16.0 KB)

看执行计划,效率差的SQL的现象是:cache_hit_count 远大于total_keys。也就是不知道为何做了那么多次的cache_hit_count,这个cache_hit_count是不是指的rocksdb的block的读取次数呢?

rpc time代表着啥,为啥会怎么高?

Tikv返回的慢,并行加等待导致这里时间高,本次重点不在这里。主要是想问为何tikv扫描慢。

真对select count(O_CUSTKEY) from orders b where b.O_ORDERDATE =‘1996-12-14’;这里重点是cache_hit_count数值太多,如果表的主键是varchar类型,那么可以通过_tidb_rowid排序方式回表扫描来减少block cache_hit_count。SQL做如下改写:select count(O_CUSTKEY) from orders where _tidb_rowid in (select _tidb_rowid from orders b where b.O_ORDERDATE =‘1996-12-14’ order by _tidb_rowid)。 就是让_tidb_rowid有序,减少对orders回表的block的访问次数。 但是这里的orders表的主键是o_custkey是bigint类型的聚簇表的键值,因此并无法这样子做优化。对于o_orderdate字段的索引上存在o_custkey这个rowid吧,如此一来按说不应该再回表了才对呢。

如果你检查其他地方都是正常的,那就只能优化sql了,
你优化后执行效果也有很大的改善了:+1:

其实我认为这个可以让优化器去评估,减少我们自己去做这样子的优化。

优化器 只能对现有的sql 选择一个最优的 执行计划,但它不能改变sql

其实这里本可以不改变SQL,通过访问机制来控制,只是通过rid回表扫描block的行为进行变化,这种机制在传统单库中基本都会有的。

嗯, 是的,传统数据库order 也是回表的