原创做者: 杨涛涛session
MySQL长期以来对索引的创建只容许正向asc存储,就算创建了desc,也是忽略掉。并发
好比对于如下的查询,没法发挥索引的最佳性能。性能
select * from tb1 where f1 = ... order by id desc;
select * from tb1 where f1 = ... order by f1 asc , f2 desc;
那对于上面的查询,尤为是数据量和并发到必定峰值的时候,则对OS的资源消耗很是大。通常这样的SQL在查询计划里面会出现using filesort等状态。搜索引擎
好比针对下面的表t1,针对字段rank1有两个索引,一个是正序的,一个是反序的。不过在MySQL 8.0 以前的版本都是按照正序来存储。spa
按照rank1 正向排序的执行计划,code
按照rank1 反向排序的执行计划,blog
从执行计划来看,反向比正向除了extra里多了Using temporary; Using filesort这两个,其余的如出一辙。这两个就表明中间用到了临时表和排序,通常来讲,凡是执行计划里用到了这两个的,性能几乎都不咋地。除非我这个临时表不太大,而用于排序的buffer也足够大,那性能也不至于太差。那这两个选项到底对性能有多大影响呢?排序
咱们分别执行这两个查询,而且查看MySQL的session级的status就大概能看出些许不一样。索引
经过以上两张图,咱们发现反向的比正向的多了不少个计数,好比经过扫描的记录数增长了10倍,并且还伴有10倍的临时表的读和写记录数。那这个开销是很是巨大的。那以上的查询是在MySQL 5.7 上运行的。资源
MySQL 8.0 给咱们带来了倒序索引(Descending Indexes),也就是说反向存储的索引。 这里不要跟搜索引擎中的倒排索引混淆了,MySQL这里只是反向排序存储而已。不过这个倒序存储已经解决了很大的问题。咱们再看下以前在MySQL 5.7 上运行的例子。
咱们把数据导入到MySQL 8.0,
再把原来的索引变为倒序索引,
再次看下第二个SQL的查询计划,
很显然,用到了这个倒序索引 idx_rank1_desc,而这里的临时表等的信息消失了。
固然了,这里的组合比较多,好比我这张表的字段rank1,rank2两个能够任意组合。
(rank1 asc,rank2 asc);
(rank1 desc,rank2 desc);
(rank1 asc,rank2 desc);
(rank1 desc,rank2 asc);
我把这几个加上,适合的查询好比:
Select * from t1 where rank1 = 11 order by rank2;
Select * from t1 where 1 order by rank1,rank2;
Select * from t1 where 1 order by rank1 desc,rank2;
...
等等,这里就不一一示范了。