MySQL 8.0Notes

第 26 章:临时表与内存表

zjc 于 2026-01-26 发布

这是《MySQL 8.0 源码与内核实战》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 MySQL 中“临时表”有三类:用户 TEMPORARY 表、SQL 层内部临时表和存储引擎内部临时结构。它们的生命周期、复制行为和内存策略不同。

26.1 用户临时表

CREATE TEMPORARY TABLE tmp_stat(
  user_id BIGINT PRIMARY KEY,
  amount DECIMAL(12,2)
) ENGINE=InnoDB;

特点:

  1. 会话可见;
  2. 同名临时表遮蔽普通表;
  3. 连接关闭自动清理;
  4. 不向传统复制流写入普通 DML;
  5. 某些 DDL 和复制场景有限制。

连接池长连接要显式 DROP TEMPORARY TABLE,避免残留。

26.2 内部临时表

触发场景:

  1. GROUP BY 无合适索引;
  2. DISTINCT;
  3. UNION;
  4. 派生表物化;
  5. 子查询物化;
  6. 窗口函数;
  7. ORDER BY 无法使用索引;
  8. JSON 或复杂表达式。

观测:

SHOW STATUS LIKE 'Created_tmp%';
EXPLAIN FORMAT=TREE SELECT ...;

26.3 TempTable 引擎

8.0 内部内存临时表默认使用 TempTable:

SHOW VARIABLES LIKE 'internal_tmp_mem_storage_engine';
SHOW VARIABLES LIKE 'temptable_max_ram';
SHOW VARIABLES LIKE 'temptable_max_mmap';

超过内存能力后会转磁盘 InnoDB 临时表,可能产生明显延迟。

26.4 磁盘临时表

临时表空间:

SHOW VARIABLES LIKE 'innodb_temp_data_file_path';
SELECT * FROM information_schema.innodb_session_status LIMIT 5;

大排序或大聚合会占用会话临时段,连接释放后空间可复用,文件不一定缩小。

26.5 降低临时表压力

  1. 为 GROUP BY / ORDER BY 建匹配索引;
  2. 减少返回行和列;
  3. 先过滤再聚合;
  4. 拆分复杂 SQL;
  5. 分页避免大 offset;
  6. 大报表走分析库;
  7. 控制排序缓冲和临时表阈值。

26.6 MEMORY 表

MEMORY 引擎表数据放内存,默认 HASH 索引,重启后数据清空。适合临时配置或小字典,不适合持久业务数据。

限制:

  1. 变长类型支持有限;
  2. 重启丢数据;
  3. 复制和恢复语义需谨慎;
  4. 不支持 InnoDB 事务能力。

本章小结

临时对象要区分用户临时表、内部内存临时表和磁盘临时表。查询大量落盘通常是排序、分组或物化导致,应从索引、过滤和查询结构优化。

思考题

  1. 用户临时表为什么在长连接中要显式清理?
  2. 哪些 SQL 会创建内部临时表?
  3. TempTable 超过内存后会发生什么?
  4. 如何通过索引减少排序落盘?
  5. MEMORY 表适合哪些场景?