排序优化:
问题:在where条件字段上添加索引,为什么还要在order by 字段上添加索引呢?
在MySQL中支持两种排序方式,分别是filesort和index方式(filesort比较耗时间)
index排序中,索引可以保证数据的有序性,不需要再次进行排序,效率更高
filesort排序一般在内存中进行,占用的CPU过多,如果待排序的结果较大,会产生临时文件io到磁盘进行排序,效率低
优化建议:
1.SQL中,可以在where语句和order by 语句中使用到索引,目的是避免where的全表扫描和order by的File Sort排序,但是在某些极端的情况下,也有不使用索引可能比使用索引的效率要高
2.尽量使用index完成order by排序,如果where和order by后面是相同的列就使用单列索引,不同的列就使用联合索引
3.无法使用index时,需要对FileSort方式进行调优
order by顺序错误也会导致索引失效,也是最左前缀法则
order by排序方向反了也会导致索引失效(如id升序,age降序)字段的排序方向要相同(都升序或降序)
数据未进行过滤(where未过滤)导致数据过多可能导致索引失效
总结:
1.当两个索引同时存在的时候,MySQL会自动选择最优的方案,但是随着数据量的变化,选择的索引也会随之变化
2.当范围条件和group by或者order by 的字段出现二选一时,优先观察条件字段的过滤数量,如果过滤的数据足够多,而需要排序的数据并不多时,优先把索引放在范围字段上,反之,同理
FileSort算法:双路排序和单路排序
排序的字段若不在索引列上,则filesort会有两种算法:双路排序和单路排序
双路排序 (慢)
MySQL 4.1之前是使用双路排序 ,字面意思就是两次扫描磁盘,最终得到数据, 读取行指针和
order by列 ,对他们进行排序,然后扫描已经排序好的列表,按照列表中的值重新从列表中读取
对应的数据输出
从磁盘取排序字段,在buffer进行排序,再从 磁盘取其他字段 。
取一批数据,要对磁盘进行两次扫描,众所周知,IO是很耗时的,所以在mysql4.1之后,出现了第二种
改进的算法,就是单路排序。
单路排序 (快)
从磁盘读取查询需要的 所有列 ,按照order by列在buffer对它们进行排序,然后扫描排序后的列表进行输
出, 它的效率更快一些,避免了第二次读取数据。并且把随机IO变成了顺序IO,但是它会使用更多的空
间, 因为它把每一行都保存在内存中了。