MySQL 执行引擎:排序与临时表机制深度解析

在 MySQL 高性能开发中,ORDER BY(排序)和内部临时表(Internal Temporary Table)是两类最消耗 CPU 与 I/O 资源的算子。本文将从执行流程、内存分配策略及物理存储结构三个维度进行技术总结。

一、 排序机制:FileSort 算法剖析

当查询无法利用索引的有序性时,MySQL 优化器会启动 FileSort。根据单行数据的大小,系统会选择不同的排序模式。

1. 全字段排序 (Full-row Sort)

sort_buffer 空间充足且单行字节数小于 max_length_for_sort_data 时采用此模式。

  • 执行步骤
    1. 从磁盘读取符合 WHERE 条件的行。
    2. 提取 SELECT 指定的所有列和 ORDER BY 涉及的列。
    3. sort_buffer 中进行排序。
    4. 排序完成后,直接返回结果集。
  • 内存代价 :由于 VARCHAR 在此阶段会被展开为定义的最大长度,容易导致 sort_buffer 溢出。
2. RowID 排序 (Double-pass Sort)

当单行数据过大时(如包含 TEXT 或长 VARCHAR),为节省缓冲区空间而采用。

  • 执行步骤
    1. 仅提取 ORDER BY 字段和主键 ID(RowID)放入 sort_buffer
    2. 排序完成后,通过主键 ID 回表 读取 SELECT 的其他列。
  • 权衡:减少了排序阶段的内存压力,但增加了排序后的随机磁盘 I/O 成本。

二、 内部临时表机制

当执行 DISTINCTGROUP BYUNION 或某些多表关联(Join)时,执行引擎需要建立临时表来存储中间计算状态。

1. 存储引擎的演进
  • Memory 存储引擎 :MySQL 8.0 之前默认使用。所有数据存在内存,不支持 BLOB/TEXT 字段,且 VARCHAR 会被转换为 定长 CHAR 存储。
  • TempTable 存储引擎:MySQL 8.0 引入的默认引擎。支持变长字段存储,提高了内存利用率。
2. 内存到磁盘的退化触发

当临时表的大小超过 tmp_table_sizemax_heap_table_size 的阈值时,MySQL 会将内存临时表转换为磁盘临时表(使用 InnoDBMyISAM 引擎),此过程涉及大量磁盘写 I/O。

三、 内存分配中的定长处理逻辑

在排序缓冲区或内部临时表中,MySQL 对 VARCHAR 类型的处理与磁盘存储存在显著差异。

1. VARCHAR 的"膨胀"现象

为了实现 O(1)O(1)O(1) 的随机访问(Random Access),执行引擎在内存中对 VARCHAR(n) 采取定长排布。

  • 示例 :定义 VARCHAR(255),字符集 utf8mb4
  • 物理存储 :存入 "abc" 仅占 3 字节 + 长度前缀。
  • 排序/临时表内存 :分配 255×4=1020255 \times 4 = 1020255×4=1020 字节。
2. 影响分析
  1. 排序效率 :单行占用的内存越大,sort_buffer 容纳的行数越少。
  2. 磁盘归并 :当行数超出限制,会产生 Sort_merge_passes,即将中间结果写入磁盘临时文件进行归并排序。
  3. 索引失效:即使定义了前缀索引,也无法在排序阶段利用索引。
相关推荐
花青泽5 分钟前
5-数据库-SQL注入-联合查询-关键字绕过-day13
数据库·sql
天桥下的卖艺者6 小时前
使用scitable包,两步生成逆概率删失权重(IPCW)
数据库·r语言
隔窗听雨眠7 小时前
AI原生数据库浪潮:国产数据库的架构重构与路径之争
数据库
数据库小学妹7 小时前
数据库选型实战:从数据类型到TCO成本,五维决策框架+九款产品横评
数据库·信创·国产数据库·数据库选型·oracle迁移
神龙天舞20018 小时前
MySQL 备库为什么会延迟好几个小时
android·数据库·mysql
丙氨酸長鏈9 小时前
Web前端入门第 问:JavaScript 一个简单的 IndexedDB 数据库入门示例
前端·javascript·数据库
独行侠影a10 小时前
APScheduler+Redis 分布式定时任务:解决多实例任务重复执行
数据库·redis·分布式
传说故事10 小时前
数据库中一些常用英文单词含义
数据库·oracle
夏贰四11 小时前
中小企业搭建业务中台如何控成本?业务中台轻量化落地分几步实施?
数据库·业务中台
林焱RPA11 小时前
影刀RPA200篇纪念版:最实用的20个自动化场景大盘点
数据库