Mysql ORDER BY优化总结

ORDER BY优化

  • 尽量对较少的行进行排序

  • 如果连接了多张表,ORDER BY的列应该属于连接顺序的第一张表

  • 利用索引排序,如果不能利用索引排序,那么EXPLAIN查询语句将会看到有filesort

  • 需要保证索引列和ORDER BY的列相同,且各列均按相同的方向进行排序

索引排序

  1. order by单一列时,在该列建立索引

  2. order by多列时, 建立联合索引,order by满足索引最左前缀

  3. 建立联合索引,使where子句与order by子句条件列组合满足索引最左前缀

filesort排序

  • 双路排序

    这是旧的算法。列长度之和超过max_length_for_sort_data字节时就使用这个算法,其原理是:先按照WHERE筛选条件读取数据行,并存储每行的排序字段和行指针到排序缓冲(sort buffer)。如果排序缓冲大小不够,就在内存中运行一个快速排序(quick sort)操作,把排序结果存储到一个临时文件里,用一个指针指向这个已经排序好了的块。然后继续读取数据,直到所有行都读取完毕为止。这是第一次读取记录。然后合并如上的临时文件,进行排序。然后依据排序结果再去读取所需要的数据,读入行缓冲(row buffer,由read_rnd_buffer_size参数设定其大小)。这是第二次读取记录。以上第一次读取记录时,可以按照索引排序或表扫描,可以做到顺序读取。但第二次读取记录时,虽然排序字段是有序的,行缓冲里存储的行指针是有序的,但所指向的物理记录需要随机读,所以这个算法可能会带来很多随机读,从而导致效率不佳

  • 单路排序

    MySQL一般使用这种算法。其原理是:按筛选条件,把SQL中涉及的字段全部读入排序缓冲中,然后依据排序字段进行排序,如果排序缓冲不够,则会将临时排序结果写入到一个临时文件中,最后合并临时排序文件,直接返回已经排序好的结果集

优化filesort

  • 加大 max_length_for_sort_data 参数的设置

    当所有返回字段的最大长度小于这个参数值时,MySQL 就会选择改进后的单路排序,反之,则选择老式的双路排序。所以,如果有充足的内存让MySQL 存放须要返回的非排序字段,就可以加大这个参数的值来让 MySQL 选择使用改进版的排序算法。

  • 去掉不必要的返回字段

    当内存不是很充裕时,不能简单地通过强行加大上面的参数来强迫 MySQL 去使用改进版的排序算法,否则可能会造成 MySQL 不得不将数据分成很多段,然后进行排序,这样可能会得不偿失。此时就须要去掉不必要的返回字段,让返回结果长度适应 max_length_for_sort_data 参数的限制。

  • 增大 sort_buffer_size 参数设置

    增大sort_buffer_size并不是为了让MySQL选择改进版的排序算法,而是为了让MySQL尽量减少在排序过程中对需要排序的数据进行分段,因为分段会造成 MySQL 使用临时表来进行交换排序。