临时表默认用MEMORY引擎;其大小受tmp_table_size和max_heap_table_size中较小值限制,超限或含不兼容字段时自动退化为磁盘表(InnoDB或MyISAM)。

临时表默认用什么引擎?tmp_table_size 和 max_heap_table_size 怎么影响它?
MySQL 创建内部临时表时,优先尝试用 MEMORY 引擎,但前提是表结构支持(比如不能有 TEXT、BLOB、JSON 列,也不能有全文索引),且数据量没超过限制。这个“限制”由两个配置共同决定:tmp_table_size 和 max_heap_table_size,取其中较小值。
- 如果临时表超出该阈值,或含不兼容字段,MySQL 会自动退回到磁盘表,用
InnoDB(8.0+ 默认)或MyISAM(旧版本) - 这个过程完全自动,你写
SELECT ... GROUP BY ... ORDER BY ...时根本看不到建表语句,但执行计划里可能看到Using temporary - 修改这两个值只影响内部临时表,不影响你显式
CREATE TEMPORARY TABLE的行为
实操建议:
- 查当前限制:
SHOW VARIABLES LIKE 'tmp_table_size';和SHOW VARIABLES LIKE 'max_heap_table_size'; - 调大前先确认内存余量,盲目设到 1G+ 可能引发 OOM,尤其在高并发场景
-
tmp_table_size是会话级变量,可在线改:SET SESSION tmp_table_size = 268435456;(256MB)
想强制让内部临时表走 InnoDB,而不是 MEMORY?
MySQL 没有提供开关来“强制指定内部临时表引擎”。这是设计上的硬限制 —— 内部临时表引擎选择是优化器根据数据特征和配置自动决策的,用户不可干预。
- 你能控制的只有“让它大概率落到磁盘”,比如:
- 在查询中引入一个
TEXT字段(哪怕只是CAST('x' AS TEXT)) - 确保结果集大小稳超
min(tmp_table_size, max_heap_table_size)
- 在查询中引入一个
- 但这样做的代价是性能下降,且不可靠:万一后续 MySQL 版本优化了 TEXT 处理,逻辑就失效了
- 真正需要稳定引擎控制的场景,应该放弃依赖内部临时表,改用显式
CREATE TEMPORARY TABLE
显式创建临时表时,怎么指定引擎?
这时你完全可控:CREATE TEMPORARY TABLE 支持 ENGINE 子句,且只接受当前启用的存储引擎。
常见写法:
CREATE TEMPORARY TABLE tmp_orders ( id BIGINT, amount DECIMAL(10,2) ) ENGINE=InnoDB;
注意点:
-
ENGINE=MEMORY表不支持TEXT/BLOB,也不支持外键、行锁、崩溃恢复 -
ENGINE=InnoDB临时表从 5.6 起支持,8.0 成为默认;它支持事务、行锁、崩溃安全,但比MEMORY慢 - 如果指定的引擎未启用(比如禁用了
InnoDB),会报错:Unknown storage engine 'InnoDB' - 临时表的
ENGINE设置**不会继承**会话的default_storage_engine,必须显式写
为什么改了 default_tmp_storage_engine 没生效?
default_tmp_storage_engine 这个变量 只对显式 CREATE TEMPORARY TABLE 生效,且仅当语句里没写 ENGINE 子句时才起作用。
- 它对内部临时表(优化器自建的)完全无效
- MySQL 8.0.13 起已将该变量标记为 deprecated,未来会移除
- 查看是否启用:
SHOW VARIABLES LIKE 'default_tmp_storage_engine'; - 设置方式(仅影响后续无 ENGINE 的显式建表):
SET SESSION default_tmp_storage_engine = InnoDB;
容易踩的坑:
- 以为设了
default_tmp_storage_engine就能控制所有临时表,结果发现慢查询里的Using temporary还是走MEMORY或磁盘MyISAM - 在 RDS 或云数据库上,该变量可能被平台锁定无法修改
- 显式建临时表时漏写
ENGINE,又没设default_tmp_storage_engine,则回退到全局default_storage_engine(通常是InnoDB),但行为不直观
临时表引擎这事,表面是配个参数,实际是分清楚“内部自动建的”和“你自己写的”两类场景——前者只能引导,后者才能掌控。多数人卡住,是因为试图用 default_tmp_storage_engine 去治 GROUP BY 慢的问题,而真正该调的是 tmp_table_size 或重写 SQL。











