Mysql利用索引进行order by排序优化

Mysql利用索引进行order by排序优化

背景

在mysql数据库中,我们一般都会设计一个id作为一张表的主键,mysql也会默认为我们的id主键建立索引,在innnodb中我们称之为聚合索引。总之,mysql为id主键创建索引这件事情我们是清楚的。

一般管理系统中,我们查询数据的时候,会根据业务需要对数据进行排序,于是需要我们sql语句中用到order by。我们来看一下下面这个sql语句,其中event_time设置了索引,id为主键。

select * from dac_log where event_time > "2020-12-29" and event_time < "2020-12-30" order by id desc; 

乍一看,这个sql没什么问题,查询条件使用了索引,id也是索引,于是就得出都会走索引的错误判断。

下面我们来分析一下上面sql语句的问题在哪。

order by + [字段] 对sql查询性能的影响

 SELECT * FROM dac_log WHERE event_time >= "2021-01-25" AND event_time <= "2021-01-26" 
 order by id ASC limit 50; //耗时7.8秒
 SELECT * FROM dac_log WHERE event_time >= "2021-01-25" AND event_time <= "2021-01-26" 
 order by event_time ASC limit 50; //耗时0.038秒

可见order by 后面的字段对sql查询性能影响极大。

我们使用explain来分析两个sql的区别:
在这里插入图片描述

对于order by + id和event_time的相同点和不同点有:

  • 可以看到连个sql语句都同时使用了index_event_time,扫描行数都是417774(总数700多万),说明event_time索引生效。
  • Filtered这个字段表示存储引擎返回的数据在server层过滤后,剩下多少满足查询的记录数量的比例,越大越好。
  • Extra字段,使用id进行排序出发了Using filesort,即表示MySQL中无法利用索引完成的排序操作称为“文件排序”

也就是说,order by id的sql语句没有使用索引进行排序,导致查询出来的sql,还需要在存储引擎层更具字段id的值进行排序,导致性能地下。

Limit关键字对sql查询性能的影响

  • 在没有添加limit的情况,为查询满足条件的数据,会对整个表进行扫描。
  • 比较常见的分页查询limit 0, 100和limit 10000,100的性能差距主要是在offset,offset前的数据都是不必要的查询。

你可能感兴趣的:(数据库mysql,后端)