数据库 filesort 排序方式
数据库 filesort 排序方式
当 MySQL 不能使用索引排序的时候,就会利用自己的排序算法(快速排序算法)在内存(sort buffer)中。如果内存装不下,它会将磁盘上的数据进行分块,再对各个数据块进行排序,然后将各个块合并成有序的结果集(实际上就是外排序)。
对于 filesort,MySQL 有两种排序方法
两边扫描算法(Two passes)
实现方式是先将需要排序的字段和可以直接定位到相关行数据的指针信息取出。然后在设定的内存(通过参数 sort_buffer_size 设定)中进行排序,完成排序之后再次通过行指针信息取出所需的列。
注:这是 4.1 版本之前的算法,它需要两次访问数据,尤其是第二次读取操作会导致大量的随机 I/O 操作。另一方面,内存开销较小。
一次扫描算法(Single pass)
该算法一次性将所需的列全部取出,在内存中排序后直接将结果输出。
注:从 MySQL 4.1 开始使用此算法。它减少了 I/O 的次数,效率较高,但是内存开销也较大。
我们将不需要的列也取出来,就会极大的浪费排序过程需要的内存。可以通过设置 max_length_for_sort_data 参数来控制 MySQL 选择第一种排序算法还是第二种。当取出的所有字段总大小大于该值,就使用第一种排序算法,反之选择第二种。为了尽可能的提高排序性能,我们偏向使用第二种排序算法,所以在 Query 中仅仅取出需要的列是非常有必要的。
当对连接操作进行排序时,如果 ORDER BY 仅仅引用第一个表的列,MySQL 对该表进行 filesort 操作,然后进行连接处理,此时 EXPLAIN 输出“Using filesort”。否则,MySQL 必须将查询结果集生成一个临时表,在连接完成之后进行 filesort 操作,这时 EXPLAIN 输出“Using temporary; Using filesort”。