Sort Buffer是每个排序线程独占的私有内存,非共享;默认256KB~1MB,高并发下内存占用线性叠加;全字段排序易爆内存,rowid排序省内存但增加回表IO;超限必落盘归并排序,性能断崖下降。

Sort Buffer 是每个排序线程独占的内存空间
MySQL 不会为所有查询共用一块排序内存,而是为每个执行 ORDER BY(或 GROUP BY、DISTINCT)的线程单独分配一块 sort_buffer。这块内存由 sort_buffer_size 参数控制,默认值通常在 256KB~1MB 之间,具体取决于版本和配置。
这意味着:并发执行 10 个带排序的查询,就可能占用 10 × sort_buffer_size 的内存——不是共享,是叠加。
- 它不从 InnoDB buffer pool 里划拨,是独立申请的线程私有内存
- 即使只查 1 行,只要用了
ORDER BY,也会初始化这个 buffer(哪怕只放 1 个id和 1 个name) -
sort_buffer_size是动态参数,SET SESSION sort_buffer_size = ...只影响当前连接,SET GLOBAL才影响新连接
全字段排序 vs rowid 排序:内存用量差异极大
MySQL 默认倾向把所有 SELECT 列都塞进 sort_buffer(全字段排序),但真正参与排序的往往只有 1~2 个字段。比如:
SELECT id, name, email, phone, address FROM users WHERE status = 1 ORDER BY name;
这里只有 name 决定顺序,但默认会把整行 5 个字段都加载进 buffer——尤其是 address 是 TEXT 类型时,单行就可能超 10KB,几十行就撑爆默认 256KB 的 sort_buffer。
这时 MySQL 会检查 max_length_for_sort_data(默认约 1024 字节):如果单行参与排序的字段总长度超过它,就自动切到 rowid 模式——只放 name 和 id 进 buffer,排完再回表查其余字段。
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
- rowid 模式省内存,但多一次回表(
id主键查找),IO 增加 - 全字段模式少 IO,但内存压力大,容易触发磁盘临时文件
-
max_length_for_sort_data设太小(如 16),可能让简单查询也降级;设太大(如 8192),又可能让大字段误入内存排序
为什么“够用”也不代表不耗内存?
即使数据量远小于 sort_buffer_size,MySQL 仍会按预估大小一次性分配整块 buffer。例如:sort_buffer_size = 2M,而实际只排序 100 行、每行 100 字节(共 10KB),它依然占着 2MB——不会动态缩容。
更关键的是:buffer 分配发生在执行初期,MySQL 无法提前知道最终有多少行满足 WHERE 条件。所以它按最坏情况预留空间,尤其当索引范围扫描(如 city = '杭州')返回大量记录时,buffer 很快被填满。
- 没走索引的
ORDER BY(全表扫描 + 排序)最容易爆内存 -
LIMIT对内存占用几乎无缓解作用——MySQL 必须先把所有符合条件的行排完,才能取前 N 条 - 使用
EXPLAIN看执行计划时,出现Using filesort就说明已超出内存,正在写磁盘临时文件
临时文件排序不是“备选方案”,而是内存不足时的必然 fallback
一旦 sort_buffer 装不下,MySQL 就必须用磁盘临时文件做归并排序(multi-pass external sort)。过程是:先分批读数据 → 每批在内存排序 → 写入一个临时文件 → 最后合并多个有序文件。
这个过程本身不报错,但性能断崖式下降:I/O 成为主导,且临时文件路径由 tmpdir 控制,若该目录在慢速磁盘或空间不足,会直接卡死查询。
- 临时文件名形如
MLyyyyyy,位于tmpdir下,不会自动清理,需 DBA 定期检查 -
read_rnd_buffer_size影响排序后回表读取的效率,但它和sort_buffer_size是两个独立参数,别混淆 - 高并发下多个查询同时写临时文件,可能引发磁盘 I/O 争抢,比单次慢更致命
sort_buffer_size 配得太保守,或者 max_length_for_sort_data 没对齐业务字段长度,导致本可内存排的查询被迫落盘。

















