《MySQL学习》 Order by 工作原理
一.排序缓存 sort_buffer
当我们使用explain 分析一条带有排序操作的SQL语句时,会看到Extra中有使用 Using filesort
explain select * from t order by k desc
MySQL 会为每个线程分配固定大小的 sort buffer 用作排序。 sort buffer 是具有逻辑概念的内存区域,大小由 sort_buffer_size 参数控制,默认为 256 kb。
当如果对一个索引字段进行排序的话,则不会使用额外的排序内存(也有可能是磁盘空间),因为索引本身是有序的。
sort_buffer_size 的值越少,需要使用的外部空间越多。 因为排序需要在排序内存中进行。比如查询出10G的数据需要排序,而排序内存只有1G,那么就要分10次进行排序,每次排序的结果放在一个外部临时文件中,因此总共需要10个外部临时文件,最终将10个排好序的文件合并到一个文件中(归并排序)。
二.单路排序 和 双路排序
如果需要排序的字段太多,MySQL将使用双路排序,反之则使用单路排序。
通过 设置 max_length_for_sort_data 的值,可以控制每次排序字段的最大长度。
单路排序将要排序的字段以及需要返回给客户端的字段全部读入排序内存中(可能使用到临时文件),排好序后直接返回。
双路排序是在需要查询的字段超过 max_length_for_sort_data 的值时使用,此时将只把需要排序的字段以及主键索引值读入排序内存中,排好序后再回表根据索引值去获取需要的字段数据,再返回给客户端。需要额外的磁盘IO操作,消耗性能。
因此,最优的方式是对排序的字段以及需要返回的字段建立联合索引,通过使用覆盖索引,避免回表以及排序。