表t的结构见MySQL索引规划。
explain select a, b from t where a > 1000 and a < 10000 order by b desc limit 1000;
Extra中包含Using filesort表示需要排序,在排序时,MySQL会为每个线程分配一块内存区域用于排序,称之为sort_buffer。
全字段排序过程
上述语句的排序过程如下:
排序过程的发生位置?
上述排序过程可能在内存中完成,也可能需要使用外部排序,主要取决于排序所需要的内存和参数sort_buffer_size。
什么是sort_buffer_size?
sort_buffer_size是MySQL为排序开辟的内存大小,如果排序的数据量小于sort_buffer_size,排序就在内存中进行,相反内存如果放不下的话,就需要借助磁盘临时文件进行排序。
如何查看是否使用了临时文件进行排序?
/* 打开optimizer_trace,只对本线程有效 */
SET optimizer_trace='enabled=on';
/* 执行语句 */
select a, b from t where a > 1000 and a < 10000 order by b desc limit 1000;
/* 查看 OPTIMIZER_TRACE 输出 */
SELECT * FROM `information_schema`.`OPTIMIZER_TRACE`\G
上图来源于MySQL官网:
rowid排序
上述的全字段排序优点是在我们整个过程中我们只对原表数据扫描了一遍,其他都在sort_buffer或者临时文件中进行,但是全字段排序也有弊端:
MySQL如何知道需要使用rowid排序?
MySQL可以通过max_length_for_sort_data参数来进行控制,如果单行的长度超过该值,MySQL会认为该行很大,需要切换到rowid算法。
rowid排序过程
根据索引直接返回
假设我们order by时有索引正好符合我们的要求,此时就不需要再借助内存或临时文件进行排序,而是直接利用有序遍历索引树直接返回结果。