- 前言
在一次上线之后,发现一个列表查询出来的数据只有9条,但是数据出来的时间竟达到了3秒多。疑惑啊!
- 查找
经过服务的监控以及慢sql的查找,最终定位到是一条查询sql耗时3秒多。如下:
SELECT * FROM account WHERE type = ? ORDER BY create_date LIMIT 10;
- 分析
看起来sql很正常啊!接下去用EXPLAIN分析:
查询的时候是create_date做索引的,也只扫描到了10行,EXPLAIN显示一切都很正常。
接下去发现其实总数据其实只有9条,但是我们查询的时候是limit了10,不知道和这个有没有关系?
无奈之下只能开始查询各种资料。。。
- 结果
最终发现是和之前的猜测相同。当limit的数据小于查询总数据量的时候,只要orderby有索引,数据会很快返回,此时使用的是索引排序。但是当limit的数据大于查询的总数据量的时候,这时候就要花里胡哨了。此时使用的是文件排序,他会全表从头开始扫描,直到把整个表都扫描完。最后不管够不够limit的数量,都会将结果返回。
此时如果where的子查询中条件若是有索引,也是可以避免我这种查询耗时很长的情况。
- 总结
order by和limit连用其实是有很多注意点,包括会导致分页查询,不同页查询到同一个数据的情况。
当然都是可以通过一些方法解决,比如在limit前,count下总数据;指定主键id范围进行查询等,但是用的时候需要自己注意。
最后记录下,mysql客户端直接查询慢sql的方法:
SELECT * from information_schema.`PROCESSLIST` where COMMAND<>'Sleep';