最近了解到,mysql 的排序也需要满足 [前导列 /最左前缀] 原则才会走索引排序,不然就是 filesort 。
之前一直没留意过,工作中大量使用主键 id 排序,用 explain 分析后发现几乎都是走 filesort,不管是
select * where a=123 order by id desc;
select id, a,b,c where a=123 order by id desc;
都无法走主键索引进行排序,id 是自增主键,a 列有索引,查询可以用到 a 列的索引,但排序依旧走 filesort.
按理说,主键也有索引,为什么无法使用索引进行排序呢?
1
OysterQAQ 2020-10-22 12:17:09 +08:00 via iPhone
每次查询只能命中一个索引,解决方法,加联合索引(a,is)
|
2
user8341 2020-10-22 12:18:00 +08:00
a 列的索引是按照 a 的大小顺序排列的,不是按照 id 的大小顺序排列的。
|
3
OysterQAQ 2020-10-22 12:22:16 +08:00 via iPhone 1
了解下索引排序的原理就明白了……本身索引是有序的才可以做到排序,order 之前的筛选项还得是=
|
5
user8341 2020-10-22 12:26:37 +08:00
为什么不用主键索引?因为没用吧。
你按 A 的索引找到一组记录,他们的 ID 是乱序的。 然后你怎么用 ID 索引去排序?我是想不出来有什么办法。 如果你先用 ID 的索引,那也没用,因为不符合 where 里面的条件,只能全表扫描,用不到索引。 |
7
user8341 2020-10-22 12:32:20 +08:00
@NULL2020 一楼说的没错啊。联合索引(a, id)就是按照 A 为主要关键字,id 为次要关键字排序。所以用这个索引,如果你 A 的条件是 = 的,ID 就是有序的。
但是如果 A 条件是>, <之类的,恐怕 ID 还是无序,还是要 filesort 。 |
9
OysterQAQ 2020-10-22 12:43:01 +08:00 via iPhone
@user8341 建议实际上看看查询计划再说吧,不知道你有没有看过高性能 mysql,里面确实有说到几个单列索引的索引合并,但是实际上你应该去看看你的执行计划,这也是书中一直强调的,在不是很了解内部实现的情况下,以查询计划为主
|
11
NULL2020 OP @user8341 #10 他解答了我的问题啊, [一个查询只能命中一个索引] ,所以假如 where 条件里命中了索引,那排序就不会命中,只能 filesort
|
12
user8341 2020-10-22 16:37:42 +08:00
|
13
wakzz 2020-10-22 20:03:50 +08:00
楼主你确定你使用了 a 字段索引?如果使用了 a 字段索引,那么排序直接使用 a 索引,不需要额外排序也就是不需要 filesort 。
|