优先用 memory,内存不足时 mysql 5.7 及以前自动降级为 myisam,8.0+ 默认改用 innodb;myisam 仅在特定旧环境或可控 olap 场景中有用,但 8.0 默认禁用且需手动启用。

临时表用 MEMORY 还是 MyISAM?先看内存够不够
MySQL 创建临时表时,默认优先用 MEMORY 引擎——但它有个硬限制:tmp_table_size 和 max_heap_table_size 中的较小值。一旦结果集超过这个阈值,MySQL 会自动降级为磁盘表,并默认选 MyISAM(在 MySQL 5.7 及更早版本)或 InnoDB(8.0+ 默认行为已改)。所以“MyISAM 在临时表中有优势”其实是个过时认知,只在特定旧环境成立。
- MySQL 5.7 及之前:临时表超内存 → 自动切到
MyISAM,因它无事务开销、建表快、索引轻量 - MySQL 8.0+:默认改用
InnoDB做磁盘临时表,更安全但写入略重;若仍想用MyISAM,得显式指定CREATE TEMPORARY TABLE ... ENGINE=MyISAM -
MEMORY表不支持TEXT/BLOB类型,一用就强制落地,此时MyISAM是少数能直接承载这类字段的轻量磁盘引擎
为什么有人还在手动指定 ENGINE=MyISAM 做临时表?
不是因为它快,而是因为“可控”——尤其在 OLAP 类中间计算、ETL 拆分步骤中,开发者需要避免事务日志、崩溃恢复等干扰,同时又要比纯内存表更稳。
-
MyISAM不写 redo/undo 日志,临时表反复创建销毁时 I/O 更干净 - 对
GROUP BY+ORDER BY大结果集,MyISAM的键缓冲(key_buffer_size)可单独调优,不和 InnoDB 的缓冲池争资源 - 注意:
MyISAM表级锁在并发多临时表操作时几乎无影响(因临时表 session 级隔离),这点反而成了优势 - 但 MySQL 8.0.16 起已移除
MyISAM全文索引支持,若临时表依赖MATCH ... AGAINST,这条路就走不通了
实际踩坑:MyISAM 临时表在 8.0 下可能根本建不起来
MySQL 8.0 默认禁用 MyISAM(skip_myisam=ON),且系统表全转 InnoDB。如果没检查配置,CREATE TEMPORARY TABLE t ENGINE=MyISAM 会直接报错:Unknown storage engine 'MyISAM'。
- 查是否启用:
SHOW ENGINES;看MyISAM行的SUPPORT列是不是YES - 启用需在配置文件加
skip_myisam=OFF并重启 mysqld(生产环境慎用) - 替代方案更现实:用
InnoDB临时表 + 关闭 autocommit(SET autocommit = 0),避免每条 INSERT 都刷 log - 或干脆用派生表(
FROM (SELECT ...))或 CTE(WITH),让优化器自己决定底层存储,更省心
真正该关心的不是引擎,而是临时表是否真必要
很多场景下,所谓“用 MyISAM 优化临时表”,本质是 SQL 写法或索引设计有问题。比如大表 JOIN 后 GROUP BY 导致临时表暴增,调优优先级永远高于换引擎。
- 先看
EXPLAIN输出里的Using temporary是否可消除(加联合索引、改 JOIN 顺序、减少 SELECT *) -
sort_buffer_size和read_rnd_buffer_size调得太小,也会把本可在内存排完的临时结果强行落地 - 临时表出现在慢查询里?大概率是逻辑可以拆解,而不是引擎不够快
引擎只是最后一道闸门,别让它替 SQL 背锅。











