filesort 是 MySQL 对无法利用索引排序时触发的内部排序流程统称,实际策略依数据量和配置动态选择单路或双路排序,核心是通过索引优化避免其触发。
MySQL 中的 filesort 并不是一种特定的排序算法名称,而是 MySQL 优化器对“无法利用索引完成排序”时所触发的**内部排序流程的统称**。它背后实际使用的排序策略取决于数据量、系统配置和字段类型,核心目标是尽可能高效地完成 ORDER BY 或 GROUP BY 所需的排序。
当查询中包含
ORDER BY(或 GROUP BY)且没有可用的索引完全覆盖排序列+查询所需列时,MySQL 就必须额外排序。常见触发场景:
(a,b,c),但排序是 ORDER BY b,c)ORDER BY UPPER(name))MySQL 5.7 及以后默认采用“双路排序”(two-pass sort)的变体,但实际行为由 sort_buffer_size 和数据特征动态决定:
MySQL 会根据 max_length_for_sort_data 参数权衡:若预计单行总长度 ≤ 该值,倾向单路;否则退回到双路。可通过 EXPLAIN 输出中的 Extra 字段观察:Using filesort 表示触发,但不区分单/双路;Using index for group-by 或 Using index 则说明未触发 filesort。
这些参数不改变算法本质,但显著影响是否落盘、用时长短:
sort_buffer_size:每个连接独享的内存缓冲区,默认 256KB。太小 → 频繁磁盘排序;太大 → 内存浪费甚至 OOM。建议按并发连接数 × 平均大小预估,线上一般设为 2MB–8MB。read_rnd_buffer_size:配合双路排序使用,控制回表读取时的随机读缓存大小。增大可减少回表 I/O 次数。tmp_table_size 和 max_heap_table_size:限制内存临时表上限。filesort 中若需建临时表(如 DISTINCT + ORDER BY 组合),超限会转磁盘(MYI/MYD),大幅拖慢速度。根本思路是让排序“走索引”,消除额外排序步骤:
ORDER BY 字段建立单独索引,或设计复合索引使其最左前缀匹配排序条件(注意 ASC/DESC 一致性)SELECT *,只查真正需要的列 —— 减少单路排序的数据体积,也利于覆盖索引OFFSET 很大)慎用 ORDER BY ... LIMIT m,n,改用游标分页(记录上一页最大 ID)Sort_merge_passes 状态变量:持续增长说明频繁磁盘归并,需调参或优化索引理解 filesort 不是为了手动干预其内部排序逻辑(比如选 quicksort 还是 mergesort),而是看清它何时出现、为何变慢,并通过索引与查询重构把它“消灭”在源头。