order by 关心的问题是排序问题,含义是order by的过程中是使用索引排序(using index)还是产生filsort这种排序

一.在索引列上的排序(可能会是using index,也可能会产生using filesort)

A.order by 遵循最佳左前缀原则

a.where后面的内容是个整体,mySql会整体进行优化的,所以可以不考虑顺序

联合索引ddl 联合索引 order by排序问题_字段


b.虽然会整体优化,但不会对order by 之后的内容做局部优化

联合索引ddl 联合索引 order by排序问题_字符串_02


c.范围查询后索引依旧会失效

注:组合索引的顺序是age在前,birth在后

联合索引ddl 联合索引 order by排序问题_mysql_03


d.索引失去带头大哥会出现using filesort

注:组合索引的顺序是age在前,birth在后

联合索引ddl 联合索引 order by排序问题_字符串_04


分析:这里出现using index的原因是先在age上进行排序(using filesort),然后再使用using index中的birth字段进行排序

B.字段必须保证相同的顺序(同升或同降),否则会产生using filesort,如果真的需要使用ASC(desc)的话,可以翻转字符串

联合索引ddl 联合索引 order by排序问题_联合索引ddl_05


二.不在索引列上(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进行考虑的三.总结:

联合索引ddl 联合索引 order by排序问题_字符串_06