执行计划里的 Using temporary 往往被轻轻带过,但它说明 MySQL 不能直接沿现有结构返回结果,需要在执行过程中构造一个中间结果载体。
内部临时表常出现在 GROUP BY、ORDER BY、DISTINCT、UNION、派生表和部分子查询里。它不是坏事,但一旦数据量、字段宽度或排序聚合成本失控,就会从内存结构变成磁盘压力。
先把机制边界说清楚
临时表分为用户显式创建的临时表和优化器自动创建的内部临时表。这里重点看内部临时表:它常出现在 GROUP BY、ORDER BY、DISTINCT、UNION、派生表和某些子查询执行中,用来保存中间结果、去重、排序或聚合。
整体路径
上面这张图先看粗线条:宏观上,内部临时表位于执行器中间层。SQL 产生候选行后,如果现有索引顺序或流式执行无法完成去重、分组或排序,MySQL 就创建内部临时表,把中间行写进去,再基于临时表继续处理后续步骤。数据量小留在内存,超过限制或包含不适合内存的列时就会落盘。
底层流程
底层拆解先看数据结构。「临时表」至少涉及下面几类结构:
- TempTable 引擎:MySQL 8.0 默认的内部内存临时表引擎。
- MEMORY 引擎:旧版本和特定配置下常见的内存临时表方案。
- 磁盘临时表:内存放不下或字段不适配时转为磁盘存储。
- 中间结果行:保存执行阶段需要继续排序、去重或聚合的数据。
再看完整执行流程:
- 执行器发现当前路径无法流式完成结果处理。
- 创建内部临时表并确定列结构。
- 把候选行写入临时表,同时维护去重或聚合状态。
- 内存超过阈值或字段不适配时转换为磁盘临时表。
- 从临时表读取最终结果并继续 order by、having 或返回。
取舍与边界
版本差异上,MySQL 5.7 常见路径是 MEMORY 临时表,落盘后可能使用 MyISAM。MySQL 8.0 引入 TempTable 作为默认内部临时表引擎,磁盘内部临时表更多使用 InnoDB,整体崩溃安全和大字段处理能力更好,但资源成本并不会消失。
临时表最大的问题是它把一个查询变成了中间数据生产者。中间结果可能比最终返回大很多;落盘后会消耗 IO;并发下大量临时表会争夺内存、临时表空间和磁盘带宽。
典型问题:用机制化例子排查
临时表压力来自中间结果,而不是最终返回行数。DISTINCT、GROUP BY、ORDER BY 如果不能复用索引顺序,就可能先构造一张更大的中间表。
可以落到这些动作:
- 看到 Using temporary 时,不要只看最终返回行数,要估算中间输入行数。
- 让 DISTINCT、GROUP BY、ORDER BY 尽量复用同一条索引顺序。
- 大字段不要进入中间结果,先取主键集合再回表。
- 监控 Created_tmp_tables、Created_tmp_disk_tables 和临时表空间增长。
收束:临时表是执行器的中间账本
临时表不是错误,但它说明现有结构无法直接给出结果。核心链路要尽量少造中间表,分析链路则要给它隔离资源。
关于十三Tech
我是十三,All in AI Agent 方向的架构师,专注 AI 工程实践。
我相信 AI 是程序员的最佳搭档,也希望帮助每一位开发者更好地驾驭 AI。
如果你想继续跟完这套「图解 MySQL」,欢迎关注公众号 「十三Tech」。后续会继续按机制、图解和实战排查这条线更新。

