order by优化,避免filesort
filesort
当我们在MySQL执行计划中,遇到了Using filesort,这就证明MySQL在执行这条语句的时候用到了filesort,而没有使用我们的索引进行排序。所以就需要进行优化。
具体filesort的过程如下:
1、根据表的索引或者全表扫描,读取所有满足条件的记录。
2、对与每一行,存储一对值到缓冲区(排序列,行记录指针),一个是排序的索引列的值,即order by用到的列值,和指向该行数据的行指针,缓冲区的大小为sort_buffer_size大小。
3、当缓冲区满后,运行一个快速排序(qsort)来将缓冲区中数据排序,并将排序完的数据存储到一个临时文件,并保存一个存储块的指针,当然如果缓冲区不满,则不会重建临时文件了。
4、重复以上步骤,直到将所有行读完,并建立相应的有序的临时文件。
5、对块级进行排序,这个类似与归并排序算法,只通过两个临时文件的指针来不断交换数据,最终达到两个文件,都是有序的。
6、重复5直到所有的数据都排序完毕。
7、采取顺序读的方式,将每行数据读入内存,并取出数据传到客户端,这里读取数据时并不是一行一行读,读如缓存大小由read_rnd_buffer_size来指定。
优化使用索引排序
我们的目标就是优化为Using index
官网文档里边有很多优化的方法,这里就只列举其中讲到的几点。
1.select字段中只包含索引字段,避免包含无关字段。
SELECT pk, key_part1, key_part2 FROM t1
ORDER BY key_part1, key_part2;
这样避免了filesort,pk是主键,这个也是可以通过索引查询到了。如果使用*的话,涉及到了回表,这样操作,还不如直接进行filesort。不管怎样,我们日常开发过程中,都应该避免使用*。
2.使用constant查询联合order by
SELECT * FROM t1
WHERE key_part1 = constant
ORDER BY key_part2;
使用了constant查询后,之后对索引进行order by,这样做后大几率会比全表查询效率要好!
3.避免order by条件中一个desc 一个 asc
还有更多细节可以参考官方文档
还有很多原则,总之最主要的就是我们的MySQL innodby引擎使用的是B+树结构存储数据,我们要做的就是尽可能的让我们查询的字段只存在于索引树中;或者通过索引,我们能够有效的过滤出我们需要的数据id,然后回表。
https://dev.mysql.com/doc/refman/5.7/en/order-by-optimization.html
https://www.cnblogs.com/aeolian/p/10212892.html