必须同时设置 tmp_table_size 和 max_heap_table_size 且值完全相等,否则以较小值为准;仅调一个无效,需重启生效,并注意 text/blob、无索引 group by 等强制落盘场景。

必须同时设置 tmp_table_size 和 max_heap_table_size,且值完全相等
MySQL 创建内存临时表时,实际生效的是这两个参数中的较小值。只改其中一个,另一个仍为默认 16M(或更低),结果就是“调了等于没调”,查询照常落到磁盘,Created_tmp_disk_tables 持续上涨。
常见错误现象:SHOW PROCESSLIST 里频繁出现 Creating tmp table 状态;EXPLAIN 显示 Using temporary,但性能却断崖式下降。
-
配置文件中必须写在
[mysqld]段内,不能放在[client]或其他段 - 单位支持
M(如128M),不支持MB;若用字节,需写成134217728 - 示例配置(推荐起步值):
tmp_table_size = 128M max_heap_table_size = 128M
- 改完必须重启 MySQL 生效;
SET GLOBAL只影响新连接,旧连接仍用旧值
为什么改完配置后 Created_tmp_disk_tables 还是不降?
使用ydata-profiling(前身为pandas-profiling)生成全面的数据质量报告,包含相关性分析、缺失值模式和基数检测。导出交互式HTML仪表板和JSON摘要。
参数设对了 ≠ 查询就走内存临时表。以下情况会强制落盘,和内存大小无关:
- 查询中含
TEXT、BLOB字段,或VARCHAR定义过宽(如VARCHAR(2000))→ MySQL 按最大可能长度预估,直接跳过内存表 -
GROUP BY或ORDER BY列没有索引 → 中间结果无法压缩,容易超限 - 使用
UNION、DISTINCT、子查询物化,且字段宽度大(如SELECT *+ 多个长字符串)→ 内存估算激增 - 执行计划里出现
Using filesort+Using temporary组合 → 基本可判定已触发双阶段临时结构
线上配置不能只看单条 SQL,得算并发总开销
tmp_table_size 是 per-connection 分配的。设成 256M 并发 200 个连接,理论峰值就吃掉 50GB 内存——还没算 sort_buffer_size、join_buffer_size 和 innodb_buffer_pool_size。
- 安全上限建议:不超过物理内存的 10%~15%,且绝对不能超过
innodb_buffer_pool_size的 25%~30% - 中小业务建议从
64M或128M起步,结合Threads_connected和Created_tmp_disk_tables增速逐步上调 - 验证是否真正生效:
SHOW VARIABLES LIKE 'tmp_table_size';和SHOW VARIABLES LIKE 'max_heap_table_size';必须返回完全一致的数值 - 重启后务必再查一遍,避免配置文件语法错误(比如多空格、漏分号、写错段名)导致加载失败
最常被忽略的一点:调参前先看 EXPLAIN FORMAT=JSON 里有没有 "using_temporary_table": true,再结合 information_schema.INNODB_TEMP_TABLE_INFO 查活跃临时表结构——否则你优化的可能根本不是瓶颈所在。










