temptable引擎比memory更省内存,因其支持动态行格式(实测省30%~50%)、null和varchar按实际长度存储、text/blob采用off-page指针式管理,避免memory的定长预留浪费与强制落盘。

TempTable引擎为什么比MEMORY更省内存
根本不是“更快”,而是同样数据量下占内存更少,间接减少落盘概率。MySQL 5.7 的 MEMORY 引擎强制使用定长行格式:哪怕你存一个空字符串或 NULL,也会按定义的 VARCHAR(200) 预留 200 字节;而 TempTable 支持动态行格式,实际只存有效内容 + 少量元数据,实测节省 30%~50% 内存。
-
MEMORY不支持TEXT/BLOB,一遇到就直接落磁盘;TempTable把大字段 off-page 存储,内存里只留指针,照样走内存路径 - 同一张临时表含 10 万行、每行带
VARCHAR(500)和一个TEXT字段,在MEMORY下可能超限立刻写磁盘;在TempTable下仍可全程内存处理 - 行内
NULL值不占空间,VARCHAR实际长度决定开销,没有“预留即占用”的浪费
为什么GROUP BY和ORDER BY在8.0更少用临时表
这不是 TempTable 自身的功劳,而是它和 MySQL 8.0 新优化器协同的结果。旧版 MEMORY 引擎再快,也救不了优化器硬要建临时表的决策;而 8.0 的 Cost Model 能识别索引已满足分组/排序顺序,直接跳过临时表阶段。
- 执行
SELECT a FROM t GROUP BY a ORDER BY a DESC,若a上有INDEX(a DESC),8.0 的TempTable+ 新优化器可直接索引扫描,EXPLAIN显示Using index;5.7 即使有索引,仍报Using temporary; Using filesort - 窗口函数(如
RANK() OVER (PARTITION BY x ORDER BY y))在 5.7 中必须物化中间结果,必然触发临时表;8.0 解析器保留逻辑节点,优化器可尝试流式计算,避免整表缓存 - 关键点:加索引比调
temptable_max_ram更治本——TempTable是“能省则省”,但索引才是“能不建就不建”
temptable_max_ram 不设等于白用 TempTable
很多人以为把 internal_tmp_mem_storage_engine = TempTable 一配就万事大吉,其实 TempTable 引擎自己有一套独立内存池,由 temptable_max_ram 控制,且该参数不支持运行时修改,必须写进配置文件并重启。
-
tmp_table_size和max_heap_table_size在 8.0.16+ 已对TempTable失效(SELECT @@tmp_table_size会报错或返回 0),只影响用户显式创建的MEMORY表 - 默认
temptable_max_ram是物理内存的 3%,一台 64GB 机器只有约 2GB;但一个含 JSON 解析 + 多层GROUP BY的报表查询,中间结果轻松突破 3GB,立刻写入ibtmp1 - 必须在
[mysqld]段中显式设置,例如:temptable_max_ram = 4294967296(4GB),单位不建议用4G(8.0.23 前兼容性差)
为什么调大 temptable_max_ram 后 ibtmp1 还是暴涨
说明问题不在配额,而在 SQL 本身。temptable_max_ram 是兜底机制,不是性能加速器;频繁触顶本质是查询设计不合理。
-
EXPLAIN出现Using temporary但没走任何索引 → 检查GROUP BY/ORDER BY字段是否缺失联合索引,尤其注意最左前缀是否被函数(如UPPER(name))或表达式(如JSON_EXTRACT(col, '$.field'))破坏 - 查询含
SELECT *+ORDER BY time→ 若表中有TEXT或超长VARCHAR,TempTable会因行格式限制被迫提前落盘,即使总大小未超temptable_max_ram - 监控指标看
Created_tmp_disk_tables增速,而不是只盯ibtmp1文件大小;后者膨胀是结果,前者飙升才是根因信号











