range分区表order by 索引列limit 1 长时间未返回

看着更像是 TiDB 对于分区表下 order by idx_col limit m, n 执行计划太差的问题。

当前的执行计划,是对每个分区计算出 topN 后,把各个分区的数据汇总计算 topN,得到的结果应当是正确的,但是没有用好索引的本身有序性。

因为当前排序的列是主键列 dt,理想的执行计划应该是按照这样的逻辑执行:

  1. 分区键是 dt,那么各个分区之间,基于 dt 有序,分区 p1 内的 dt 值都小于分区 p2 的 dt 值
  2. 分区内 dt 是索引(主键索引),那么按照 dt 的索引,分区内 dt 是有序的

基于以上的有序性,按照顺序扫描分区表,对于分区表内部,使用 dt 的索引就可以得到 order by dt limit m, n 的结果了,也就是跟使用非分区表类似的效率,使用 limit 算子就可以了。

对于当前的结果,因为不清楚这里 dt 的类型定义,有没有这种可能:
UNIX_TIMESTAMP(dt) 的影响,就是说对 dt 列的值进行 UNIX_TIMESTAMP(dt) 后,原来 dt 值的顺序跟 UNIX_TIMESTAMP(dt) 的顺序不一致,导致可能要扫描所有的分区。
这种可能性较小,而且即使是这种影响,也不需要对分区表内执行全表扫,因为分区表内 dt 索引仍然有序,对于这样的情况,这种执行计划就行了:

  1. 对所有分区表的结果执行 topN
  2. 对于分区表内部执行 limit

所以 TiDB 对于 range 分区,这种情况,生成的执行计划不够优秀感觉有很大关系。

基于当前的执行计划,耗时较久就要看下机器性能以及扫表相关相关的参数了,毕竟表数据量大,如果磁盘性能不佳,扫描并发参数较低,130亿的数据,耗时较久很有可能的。

1 个赞