面试题:解释一下什么是全字段排序和rowid排序

「全字段排序」和「rowid 排序」这两个关键概念,它们其实是 MySQL 执行filesort(文件排序)时的两种核心算法。

先明确核心前提

这两种排序都是「没有合适索引时,MySQL 被迫做文件排序」的内部实现方式,目的都是完成 ORDER BY 的排序需求,但数据读取方式、内存占用、性能差异极大 ------MySQL 5.6+ 已默认优先使用 rowid 排序(更高效)

一、全字段排序(Full Sort)

1. 定义

排序时,把查询需要的所有字段 (SELECT 列 + ORDER BY 列 + WHERE 列)都加载到sort_buffer(排序缓冲区),排序后直接返回结果,无需回表

2. 执行原理(步骤拆解)

以这个查询为例(无覆盖索引,触发 filesort):

sql

复制代码
SELECT id, order_no FROM t_order WHERE status = 1 ORDER BY create_time DESC;

全字段排序的执行流程:

  1. 读取满足status = 1的每一行数据,把id、order_no、create_time(查询需要的所有字段)全部取出;
  2. 将这些字段的完整数据写入sort_buffer
  3. sort_buffer中按create_time DESC排序;
  4. 直接返回排序后的结果(已包含所有需要的字段,无需再查数据)。
3. 核心特点
  • ✅ 优点:排序后无需回表,少一次 IO 操作;
  • ❌ 缺点:sort_buffer内存占用大(要存所有字段),如果查询字段多(比如 SELECT *),sort_buffer容易被占满,数据会溢出到磁盘,导致排序速度骤降;
  • 适用场景:查询字段极少(比如只查 1-2 个小字段)、排序数据量小的场景。

二、rowid 排序(Rowid Sort,改进型文件排序)

1. 定义

排序时,只把「排序键(ORDER BY 指定的列) + 行指针(主键 id / 物理行地址)」加载到sort_buffer,排序后再通过「行指针」回表读取需要的字段,需要回表但内存占用小

2. 执行原理(步骤拆解)

还是以上面的查询为例,rowid 排序的执行流程:

  1. 读取满足status = 1的每一行数据,只取出create_time(排序键)和id(主键,行指针);
  2. create_time + id写入sort_buffer(仅这两个值,内存占用极小);
  3. sort_buffer中按create_time DESC排序;
  4. 按排序后的id,逐行去聚簇索引回表,读取order_no字段;
  5. 拼接id + order_no后返回结果。
3. 核心特点
  • ✅ 优点:sort_buffer内存占用极小(仅存排序键 + 主键),不容易溢出到磁盘,排序效率更高;
  • ❌ 缺点:排序后需要回表(随机 IO),但回表的开销远小于「sort_buffer 溢出到磁盘」的开销;
  • 适用场景:查询字段多(比如 SELECT *)、排序数据量大的场景(MySQL 默认优先用这种)。

三、全字段排序 vs rowid 排序(核心区别)

对比维度 全字段排序 rowid 排序
sort_buffer内容 所有查询字段(SELECT/ORDER BY/WHERE) 仅排序键 + 主键(rowid)
内存占用 小(仅前者的 1/10 甚至更少)
是否回表
触发条件 查询字段总长度 ≤ max_length_for_sort_data(默认 1024 字节) 查询字段总长度 > max_length_for_sort_data
MySQL 默认(5.6+) 仅字段极少时触发 优先使用(默认开启rowid_orderby=on
性能 字段少快、字段多慢 字段多快、字段少略慢(回表开销可忽略)

四、回表会不会让 ORDER BY 变慢

  • 如果触发 filesort 且用全字段排序:无回表,但内存占用大,字段多 / 数据量大时排序本身变慢;
  • 如果触发 filesort 且用rowid 排序:有回表,但排序本身更快,回表的随机 IO 是主要开销;
  • 但无论哪种 filesort,性能都远不如「覆盖索引 + 索引排序」

五、如何控制这两种排序(可选)

MySQL 通过max_length_for_sort_data参数控制算法选择(默认 1024 字节):

复制代码
-- 查看当前值(单位:字节)
SHOW VARIABLES LIKE 'max_length_for_sort_data';

-- 临时调整(会话级)
SET SESSION max_length_for_sort_data = 2048;
  • 如果查询字段的总长度 ≤ 这个值:用全字段排序;
  • 如果超过这个值:用 rowid 排序。

⚠️ 不建议随意调大这个值:如果查询字段多,调大后会强制用全字段排序,导致sort_buffer溢出到磁盘,反而更慢。

总结

  1. 全字段排序和 rowid 排序是filesort的两种算法,核心区别是sort_buffer存储的内容和是否回表;
  2. rowid 排序是 MySQL 5.6 + 默认方案,内存占用小,适合字段多 / 数据量大的场景;
  3. 无论哪种 filesort,性能都远低于「覆盖索引 + 索引排序」,优化 ORDER BY 的核心还是建适配的索引。
相关推荐
爱敲代码的TOM7 分钟前
数据结构总结
数据结构
Re.不晚14 分钟前
MySQL进阶之战——索引、事务与锁、高可用架构的三重奏
数据库·mysql·架构
老邓计算机毕设24 分钟前
SSM智慧社区信息化服务平台4v5hv(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·ssm 框架·智慧社区、·信息化平台
麦聪聊数据44 分钟前
为何通用堡垒机无法在数据库运维中实现精准风控?
数据库·sql·安全·低代码·架构
2301_790300961 小时前
Python数据库操作:SQLAlchemy ORM指南
jvm·数据库·python
m0_736919101 小时前
用Pandas处理时间序列数据(Time Series)
jvm·数据库·python
亓才孓1 小时前
[JDBC]PreparedStatement替代Statement
java·数据库
m0_466525292 小时前
绿盟科技风云卫AI安全能力平台成果重磅发布
大数据·数据库·人工智能·安全
皮皮哎哟2 小时前
数据结构:嵌入式常用排序与查找算法精讲
数据结构·算法·排序算法·二分查找·快速排序
爱学习的阿磊2 小时前
使用Fabric自动化你的部署流程
jvm·数据库·python