MySQL Order By 原理以及优化(2)

温馨提示 ,各位看官要辩证的看待官方给的例子,自己多动手实践。
无法利用到索引排序的情况,其实我觉得这是本文的重点,对于广大开发同学而言,记住那种不能利用索引排序会更简单些。

1 最常见的情况 用来查找结果的索引(key2) 和 排序的索引(key1) 不一样,where a=x and b=y order by id;

SELECT * FROM t1 WHERE key2=constant ORDER BY key1;

2 排序字段在不同的索引中,无法使用索引排序

SELECT * FROM t1 ORDER BY key1,key2;

3 排序字段顺序与索引中列顺序不一致,无法使用索引排序,比如索引是 key idx_kp1_kp2(key_part1,key_part2)

SELECT * FROM t1 ORDER BY key_part2, key_part1;

4 order by中的升降序和索引中的默认升降不一致,无法使用索引排序

SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC;

5 ey_part1是范围查询,key_part2无法使用索引排序

SELECT * FROM t1 WHERE key_part1> constant ORDER BY key_part2;

5 rder by和group by 字段列不一致

SELECT * FROM t1 WHERE key_part1=constant ORDER BY key_part2 group by key_part4;

6 索引本身是无序存储的,比如hash 索引,不能利用索引的有序性。

7 order by字段只被索引了前缀 ,key idx_col(col(10))

select * from t1 order by col ;

8 对于还有join的关联查询,排序字段并非全部来自于第一个表,使用explain 查看执行计划第一个表 type 值不是const 。

当无法避免排序操作时,又该如何来优化呢?很显然,优先选择using index的排序方式,在无法满足利用索引排序的情况下,尽可能让 MySQL 选择使用第二种单路算法来进行排序。这样可以减少大量的随机IO操作,很大幅度地提高排序的效率。
1 加大 max_length_for_sort_data 参数的设置
  在 MySQL 中,决定使用老式排序算法还是改进版排序算法是通过参数max_length_for_sort_data来决定的。当所有返回字段的最大长度小于这个参数值时,MySQL 就会选择改进后的排序算法,反之,则选择老式的算法。所以,如果有充足的内存让MySQL 存放须要返回的非排序字段,就可以加大这个参数的值来让 MySQL 选择使用改进版的排序算法。
2 去掉不必要的返回字段
  当内存不是很充裕时,不能简单地通过强行加大上面的参数来强迫 MySQL 去使用改进版的排序算法,否则可能会造成 MySQL 不得不将数据分成很多段,然后进行排序,这样可能会得不偿失。此时就须要去掉不必要的返回字段,让返回结果长度适应 max_length_for_sort_data 参数的限制。
 同时也要规范MySQL开发规范,尽量避免大字段。当有select 查询列含有大字段blob或者text 的时候,MySQL 会选择常规排序。
"The optimizer selects which filesort algorithm to use. It normally uses the modified algorithm except when BLOB or TEXT columns are involved, in which case it uses the original algorithm.

3 增大 sort_buffer_size 参数设置
  这个值如果过小的话,再加上你一次返回的条数过多,那么很可能就会分很多次进行排序,然后最后将每次的排序结果再串联起来,这样就会更慢,增大 sort_buffer_size 并不是为了让 MySQL选择改进版的排序算法,而是为了让MySQL尽量减少在排序过程中对须要排序的数据进行分段,因为分段会造成 MySQL 不得不使用临时表来进行交换排序。但是这个值不是越大越好:
1 sort_buffer_size 是一个connection级参数,在每个connection第一次需要使用这个buffer的时候,一次性分配设置的内存。
2 sort_buffer_size 并不是越大越好,由于是connection级的参数,过大的设置+高并发可能会耗尽系统内存资源。
3 据说sort_buffer_size 超过2M的时候,就会使用mmap() 而不是 malloc() 来进行内存分配,导致效率降低。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/6c85accf9959273f747c8a98c651f25c.html