Order by 的优化

假如tableA 有三个字段c1,c2,c3,要执行
select * from tableA order by c1,c2
select * from tableA order by c1,c2,c3
select * from tableA order by c2,c3 等操作,一般有哪些优化方法和注意呢?
1. mysql支持两种方式的排序,filesort排序和index排序, index排序的效率更高,
2. 编写SQL语句时 在索引列上遵循索引的最佳左前缀原则,对于 形如Key(c1,c2,c3)的复合索引: 一般先按照c1排序,c1相同再按照c2排序,依次类推
order by(c1,c2) 可以使用索引
order by (c1,c2,c3) 也可以使用索引
order by (c2,c3)不能使用索引
order by (c1,c2,c3) 索引字段的缺失或者复合(联合)索引字段顺序与 order by 不一致都会导致索引失效
order by c1 desc, c2 desc 可优化
order by c1 desc,c2 asc 不可优化

  1. order by 排序条件不能是一个查询表达式,否则不能使用索引
  2. order by (c1,c2) 在c1,c2上分别建立索引不能加速排序

Tips:
- 索引最左前缀原则:如果索引多列(复合或者联合索引),查询从索引的最左前列开始,并且不跳过索引中的列,否则将不能使用索引
- 覆盖索引 : 指一个查询语句的执行只需要从辅助索引中就可以得到查询记录,而不需要查询聚集索引中的记录。也可以称之为实现了索引覆盖
- mysql一次只能使用一个索引,如果要对多个字段使用索引,应建立复合索引

Group by 的优化

由于GROUP BY 实际上也同样会进行排序操作,而且与ORDER BY 相比,GROUP BY 主要只是多了排序之后的分组操作。当然,如果在分组的时候还使用了其他的一些聚合函数,那么还需要一些聚合函数的计算。所以,在GROUP BY 的实现过程中,与 ORDER BY 一样也可以利用到索引

如果有索引,使用索引; 如果没有索引,使用临时表,使用临时表排序后再分组,在执行计划中可以看到“Using temporary; Using filesort”。MySql建立的索引通常是有序的,如果通过读取索引就能完成group by操作,就可以避免创建临时表和排序。 使用索引进行group by操作的前提是所有group by的参照列来自同一个索引,且索引按照顺序存储所有的keys, mysql有两种索引扫描方式完成group by 操作:松散索引扫描、紧凑索引扫描

使用松散索引扫描(Loose index scan):

使用紧凑索引扫描(Tight index scan)实现 GROUP BY

松散索引扫描和紧凑索引扫描的最大区别是是否需要扫描整个索引或者整个范围扫描

使用临时表实现 GROUP BY

参考:
MySQL索引使用笔记 : http://www.kuqin.com/database/20130529/334520.html MySQL松散索引扫描与紧凑索引扫描
mysql中order by优化的那些事儿: http://ustb80.blog.51cto.com/6139482/1073352