之前的文章中说道mysql8.0新增了降序索引,今天针对这个性能做下测试分析。
从语法上来说,早在mysql5版本的初期,已经支持index idx_c1_c2(c1,c2 desc)的语法,但实际上它的降序排序是不生效的。
降序索引测试
mysql5.7
先看下在5.7版本下建一个降序索引会是什么情况
数据库版本:
建表语句:
可以看到即使建表时显式指定(c1,c2 desc),但建完表后,真实索引还是KEY idx_c1_c2 (c1,c2)
mysql8.0
再来看下8.0中使用相同语句会是什么情况
数据库版本:
建表语句:
果然,在8.0中建立的降序索引生效了。
降序索引作用
如有有个查询,需要对多个列进行排序,而且排序条件不一致,这种情况下,数据库会进行而外的排序 filesort
。这时候就可以使用降序索引进行优化了。
mysql 5.7
查询语句:select * from index_sort_test order by c1,c2 desc;
explain以下该语句,果然用到了filesort
mysql 8.0
同样的语句:select * from index_sort_test order by c1,c2 desc;
可以看到执行计划并未使用filesort
,在数据量很大的情况下,减少排序操作会极大加速sql的执行速度
降序索引是否能应用于单列排序的场景?
mysql 5.7
以5.7为例,查询语句如下:
select * from index_sort_test order by c1;
select * from index_sort_test order by c1 desc; #c1进行倒序排序
两条sql执行计划一致。c1是建表默认的升序索引,对单列排序(无论升序或降序),都不需要进行额外排序。
实际上,对于索引,mysql不仅支持正向扫描,还可以反向扫描。而且反向扫描的性能同样不差,下面贴个mysql官方的压测结果:
有两列(a,b),一个联合索引(a desc,b asc)
mysql 8.0
再来看下8.0里有什么不一样的地方
在降序排序的场景下,extra中多了个 Backward index scan
状态,这只是用来提醒你,mysql对该索引进行了反向扫描。
对于group by的排序
随着降序索引的加入,mysql8.0还会对group by进行隐形排序吗?
安排下模拟数据:
mysql 5.7
查询结果是升序排序1,2,3,执行计划中确实用到了filesort
mysql 8.0
在8.0版本中,该查询的结果并没有升序输出,执行计划也没用到filesort
注意点
mysql8.0对于group by操作确实不再进行隐式排序,若数据库从低版本升至8.0,务必要主要依赖group by隐式排序的业务!!