order by 关心的问题是排序问题,含义是order by的过程中是使用索引排序(using index)还是产生filsort这种排序
一.在索引列上的排序(可能会是using index,也可能会产生using filesort)
A.order by 遵循最佳左前缀原则
a.where后面的内容是个整体,mySql会整体进行优化的,所以可以不考虑顺序
b.虽然会整体优化,但不会对order by 之后的内容做局部优化
c.范围查询后索引依旧会失效
注:组合索引的顺序是age在前,birth在后
d.索引失去带头大哥会出现using filesort
注:组合索引的顺序是age在前,birth在后
分析:这里出现using index的原因是先在age上进行排序(using filesort),然后再使用using index中的birth字段进行排序
B.字段必须保证相同的顺序(同升或同降),否则会产生using filesort,如果真的需要使用ASC(desc)的话,可以翻转字符串
二.不在索引列上(using filesort)
不在索引列上进行排序就会使用using filesort
using filesort 会有两种排序方式:双路排序、单路排序(默认)
1.双路排序:
A.过程:两次I/O,第一次I/O取出指针和order by 字段进行排序,第二次I/O将记录的其余字段和排序字段进行拼接
B.缺点:两次读写I/O
单路排序:
A.过程:一次I/O,一次将全部记录读进内存进行排序
B.缺点:由于记录过大,可能一次无法将全部记录读进内存
2.怎样进行优化?
A.增大max_length_for_sort_data:如果需要排序的列的总大小+order by列的大小超过了 max_length_for_sort_data定义的字节,mysql就会使用双路排序,但是该值如果过高会导致数据的总容量>缓冲区的容量,这个时候会造成高I/O和低cpu处理
B.提高sort_buffer_size:两种算法都会超出sort_buffer的容量,超出容量后会创建临时表进行合并,导致多次I/O
C.尽量不要使用select * ,基于max_length_for_sort_data进行考虑的三.总结: