bigywater.tech
MySQL / InnoDB · 43

临时表创建与落盘

同一条GROUP BY查询,只改要不要带上一个真正的TEXT列,再对比新旧两种内部临时表引擎,看TEXT列到底会不会强制临时表落盘。

MEMORY引擎
遇到TEXT列立刻落盘,和数据量无关
TempTable引擎(默认)
同样的TEXT列不再强制落盘

做的事:同一类GROUP BY,只改要不要带上一个TEXT列

orders表加一列真正的TEXT类型(note_text),内容和已有的VARCHAR列(note)完全一样,只是类型不同。

代码ALTER TABLE orders ADD COLUMN note_text TEXT; UPDATE orders SET note_text = note; -- 对比: SELECT ym, COUNT(*), SUM(amount) FROM orders GROUP BY ym; -- 只有数字 SELECT ym, MIN(note_text) sample FROM orders GROUP BY ym; -- 带上TEXT列

验证:切回旧版MEMORY引擎,TEXT列真实立刻逼出磁盘临时表

实测 · 本机执行输出(internal_tmp_mem_storage_engine=MEMORY)
GROUP BY ym, COUNT(*), SUM(amount)(只有数字列):
  Created_tmp_disk_tables = 0

GROUP BY ym, MIN(note_text)(带上一个真正的TEXT列):
  Created_tmp_disk_tables = 1   ← 立刻落盘,不是因为数据量大,是因为列类型

把internal_tmp_mem_storage_engine手动设回旧版的MEMORY引擎后,只聚合数字列的GROUP BY,内部临时表真实还是留在内存里;但只要SELECT列表里出现了一个真正的TEXT类型的列,Created_tmp_disk_tables立刻变成1——这和数据量大小完全无关,因为MySQL经典的MEMORY存储引擎从设计上就不支持存储BLOB/TEXT这类变长大对象,只要内部临时表里需要装下一个TEXT列,MEMORY引擎当场就放弃,直接改用基于磁盘的InnoDB内部临时表。

验证:换回默认的TempTable引擎,同样的TEXT列不再强制落盘

实测 · 本机执行输出(internal_tmp_mem_storage_engine=TempTable,默认值)
GROUP BY ym, MIN(note_text)(同样带TEXT列):
  Created_tmp_disk_tables = 0   ← 换回默认引擎后,同一条查询不再强制落盘
现在MySQL 8.0.13之后默认的内部临时表引擎是TempTable,而不是旧版的MEMORY——同一条带TEXT列的GROUP BY查询,换回默认的TempTable引擎之后,Created_tmp_disk_tables真实又变回了0。TempTable引擎从设计上就移除了"不能存BLOB/TEXT"这条限制,它是否落盘只取决于数据总大小有没有超过temptable_max_ram这个内存上限(默认1GB),和列的数据类型无关。也就是说,"GROUP BY里出现文本列就会导致临时表落盘"这条经验,只对老版本MySQL或者手动切回MEMORY引擎的场景成立,现在的默认配置下已经不是这样了。

分步演示:三种引擎+列类型组合的真实结果

每一步都是本文上面用SHOW STATUS跑出来的原始结果。

TEXT列是否强制临时表落盘,取决于引擎版本
这一步新验证的组合

    本文用到的工具

    • 本机 MySQL 26.7.0(InnoDB),orders表新增一列真正的TEXT类型(note_text)
    • SESSION internal_tmp_mem_storage_engine(MEMORY / TempTable)+ SHOW STATUS LIKE 'Created_tmp_disk_tables'
    京ICP备2026067502号-1京公网安备11010502063487号