order by asc 和desc 响应时差不一

为提高效率,提问时请提供以下信息,问题描述清晰可优先响应。

  • 【TiDB 版本】:master

  • 【问题描述】: 对主键 order by asc, desc 有什么区别? select * from xxx_tab where batch_no = ‘xxxx’ and fee_status = 8 order by id asc; 耗时102s。 select * from xxx_tab where batch_no = ‘xxxx’ and fee_status = 8 order by id desc; 耗时 1s。

    使用explain

+------------------+-----------+------+---------------------------------------------------------------------------------------------------------------------------------------------------+
| id               | count     | task | operator info                                                                                                                                     |
+------------------+-----------+------+---------------------------------------------------------------------------------------------------------------------------------------------------+
| Sort_5           | 381710.63 | root | xxx.xxx_tab.id:asc                                                                                       |
| └─IndexLookUp_13 | 381710.63 | root |                                                                                                                                                   |
|   ├─IndexScan_11 | 381710.63 | cop  | table:xxx_tab, index:batch_no, fee_status, range:["xxx" 8,"xxx" 8], keep order:false |
|   └─TableScan_12 | 381710.63 | cop  | table:xxx_tab, keep order:false                                                                                                  |
+------------------+-----------+------+---------------------------------------------------------------------------------------------------------------------------------------------------+

若提问为性能优化、故障排查类问题,请下载脚本运行。终端输出打印结果,请务必全选并复制粘贴上传。

  • select * from xxx_tab where batch_no = ‘xxxx’ and fee_status = 8 order by id asc; 用 ACS 表示按正序排序(即:从小到大排序) — 升序排列
  • select * from xxx_tab where batch_no = ‘xxxx’ and fee_status = 8 order by id desc; 用 DESC 表示按倒序排序(即:从大到小排序) — 降序排列

我的意思是为什么会有这么大的性能差异? explain 出来的执行计划是一样的。 explain select * from xxx_tab where batch_no = ‘xxx’ and fee_status = 8 order by id asc limit 10;

除了在最后tablScan_29 多了个desc 并没有其他区别。在KiTV 内部支持desc 模式,不支持asc? 主键索引情况: PRIMARY KEY (id) KEY idx_batch_no_fee_status (batch_no,fee_status)

还有一个情况是:

换了个参数之后執行計劃不太一致,并且其中一個keep order 為true 這是否是影響性能的關鍵?

@Hacker_FrIg00OR, 麻烦用 explain analyze 看下 order by asc 和 desc 的结果吧

看起来就是扫表的时候 desc 和asc 方式耗时是不一样的。是什么原因造成这种情况呢?mysql order by 默认的排序是asc 的。

支持的,但是执行计划看,desc 走了 double read ,asc 默认应该会比 desc 快。TiDB 默认是升序的。所以这个建议收集一下统计信息,然后再测试一下。

hi,按照另一位同学的说法,進一步使用explain analyze 分析结果如上描述。从执行计划中两者看起来完全一致,为什么说desc 走了double read 呢? @SUN-PingCAP @crazycs520-PingCAP

  1. 第一个场景反馈的 explain 结果,看不出来时 desc 和 asc 哪个慢,所以要反馈 explain analyze 才可以看出来问题。
  2. 第二个场景里面可以看到上面走的 index 的 double read ,但是下面的这个 SQL 走的是全表扫。所以响应时间不一致是预期的。换 where 条件中的 谓词 的取值不一样,那么根据该列的直方图确认具体数据取值。走索引的情况下,取决于取值情况。

@SUN-PingCAP 第一个场景的 analyze 结果如下:

第二场场景意思是 先从索引表读了一次,获取到id,再次从全表读,这个过程为double read?并且选择哪种方式其实是tiDB 根据内部算法判断,用户侧其实没法选择。是这个意思吗?

那么问题主要是在第一个里,相同的谓语下,asc 和desc 的区别哈。感谢解答。

有办法选择,通过 hint 方式控制走不走索引。

预期应该 asc 比 desc 会快,因为目前主键默认是升序排列,所以 asc 应该会比 desc 会快。

emm 可是时间analyze desc 耗时1s,asc 耗时1min。和推测的似乎不太一致。

说一让你先尝试收集一下 table 的统计信息,然后再试一下。另外执行计划选择和数据分布有关系的,和其他的 RDBMS 数据库一样,如果数据存在数据倾斜,那么你查询某些数据量比较多的相同数据会走到全表扫描,

@Hacker_FrIg00OR 可以给下 asc 和 desc 执行的慢日志信息吗?

@Hacker_FrIg00OR 麻烦给下 TiDB, PD, TiKV 版本的 git_hash吧

好的 我尝试联系下DBA

多谢,有进展请反馈信息,麻烦了