文章目录
-
-
- [一、filesort 的触发场景](#一、filesort 的触发场景)
-
- [示例(触发 filesort):](#示例(触发 filesort):)
- [二、filesort 的实现方式](#二、filesort 的实现方式)
-
- [1. 内存排序(快速排序)](#1. 内存排序(快速排序))
- [2. 磁盘排序(归并排序)](#2. 磁盘排序(归并排序))
- [三、如何判断是否触发 filesort?](#三、如何判断是否触发 filesort?)
- [四、如何避免或优化 filesort?](#四、如何避免或优化 filesort?)
-
- [1. 创建"排序友好"的索引](#1. 创建“排序友好”的索引)
- [2. 调整 `sort_buffer_size`(谨慎使用)](#2. 调整
sort_buffer_size
(谨慎使用)) - [3. 减少排序的数据量](#3. 减少排序的数据量)
- 五、总结
-
在MySQL中,
filesort
是一种排序机制,当查询需要对结果进行排序(如使用ORDER BY
或GROUP BY
),且无法利用索引完成排序时,MySQL会通过内存或磁盘 对结果集进行排序,这个过程就称为filesort
。
一、filesort 的触发场景
当查询包含
ORDER BY
、GROUP BY
、DISTINCT
等需要排序的操作,且没有合适的索引 可以直接返回有序结果时,MySQL会触发filesort
。
示例(触发 filesort):
sql
-- 表中无索引或索引无法覆盖排序需求
SELECT name, age FROM user WHERE city = 'Beijing' ORDER BY age;
若
user
表仅在city
列有索引(idx_city
),该索引可加速WHERE city = 'Beijing'
的筛选,但无法提供age
的有序性,因此需要对筛选后的结果进行filesort
排序。
二、filesort 的实现方式
MySQL 的
filesort
有两种排序策略,具体使用哪种取决于结果集大小和系统变量配置:
1. 内存排序(快速排序)
- 适用场景:结果集较小,内存足以容纳排序数据。
- 过程:
- 从表中读取符合条件的记录,提取"排序字段+行指针(或主键)"组成临时数组。
- 使用快速排序对临时数组按排序字段排序。
- 按排序后的顺序,通过行指针读取完整记录并返回。
- 优点:纯内存操作,速度快。
- 限制 :受
sort_buffer_size
变量控制(默认256KB),若临时数组大小超过该值,则触发磁盘排序。
2. 磁盘排序(归并排序)
- 适用场景 :结果集较大,内存不足以容纳(超过
sort_buffer_size
)。- 过程:
- 分批次读取数据,每批数据在内存中排序后写入临时磁盘文件(使用快速排序)。
- 对所有临时文件进行归并排序,合并成一个有序的大文件。
- 从有序文件中读取记录并返回。
- 缺点:涉及磁盘IO,性能远低于内存排序,可能成为查询瓶颈。
三、如何判断是否触发 filesort?
通过
EXPLAIN
分析查询计划,若Extra
列显示Using filesort
,则表示触发了filesort
:
sql
EXPLAIN SELECT name, age FROM user WHERE city = 'Beijing' ORDER BY age;
执行结果中,
Extra: Using filesort
说明该查询需要排序且未使用索引排序。
四、如何避免或优化 filesort?
filesort
本质是"无法利用索引排序时的兜底方案",优化核心是让排序操作通过索引完成 (即"索引排序"),避免触发filesort
。
1. 创建"排序友好"的索引
将筛选条件和排序字段组合成联合索引 ,利用索引的有序性直接返回排序结果。
例如,对上述示例创建联合索引
idx_city_age(city, age)
:
sql
CREATE INDEX idx_city_age ON user(city, age);
- 该索引先按
city
筛选,同city
下按age
有序排列,查询WHERE city = 'Beijing' ORDER BY age
可直接通过索引获取有序结果,避免filesort
。
2. 调整 sort_buffer_size
(谨慎使用)
- 适当增大
sort_buffer_size
(如SET sort_buffer_size = 1M
),可让更多排序在内存中完成,减少磁盘IO。- 注意:该变量是会话级参数,过大可能导致内存资源竞争(每个连接独立分配),不建议全局调大。
3. 减少排序的数据量
- 通过
WHERE
子句提前过滤掉无关数据,缩小排序范围。- 仅查询必要字段(避免
SELECT *
),减少排序时的临时数据量。
五、总结
filesort
是 MySQL 对查询结果进行排序的机制,当无法利用索引排序时触发。- 分为内存排序(快速排序)和磁盘排序(归并排序),磁盘排序性能较差。
- 优化关键是创建包含"筛选+排序"字段的联合索引,让排序通过索引完成,避免
filesort
。通过
EXPLAIN
分析查询计划,及时发现filesort
并优化,是提升排序查询性能的核心手段。