Using temporary不是错误,仅表示优化器需建临时表处理排序或分组;真正影响性能的是是否落盘,而落盘由tmp_table_size与max_heap_table_size中较小值决定,二者必须同步调大至64MB–256MB并监控Created_tmp_disk_tables占比低于5%,根治方法是建立覆盖索引而非盲目调参。

Using temporary不是错误,但说明MySQL正在用临时表完成排序或分组
它出现在 EXPLAIN 的 Extra 列里,代表优化器无法直接用索引满足 GROUP BY、DISTINCT、UNION 或某些 JOIN 中的排序需求,被迫建内部临时表。关键风险不在“用了临时表”,而在它是否落盘——一旦超过内存上限,就会写到磁盘,性能断崖下跌。
真正决定临时表是否落盘的是 tmp_table_size 和 max_heap_table_size
这两个值取较小的那个作为内存临时表上限。只要临时表大小超过它,MySQL 就会转存为磁盘临时表(Created_tmp_disk_tables 计数上涨)。
- 必须同步设置,改一个等于白改:
SET SESSION tmp_table_size = 67108864;和SET SESSION max_heap_table_size = 67108864; - 默认值通常太小(如 16MB),生产环境建议设为 64MB–256MB,但要结合
Created_tmp_tables与Created_tmp_disk_tables的比值监控,理想应低于 5% - 该设置对已建立的连接无效,只影响新连接;也不会回滚已创建的临时表
- 在线调优可用
SET SESSION,全局生效需写入配置文件并重启或用SET PERSIST
sort_buffer_size 调大不能消除 Using temporary,但能降低排序开销
sort_buffer_size 只管单个连接内 ORDER BY 的内存排序缓冲,和临时表机制无关。它对 GROUP BY 完全无效。
- 默认值常为 256KB,对含大量数据的
ORDER BY明显不够,可按需设为 2MB–8MB - 它是每个线程独占分配,别盲目设到几百 MB,否则容易触发 OOM
- 增大后若仍出现
Using filesort,说明根本问题还是没走对索引,不是缓冲不够
最有效的解法永远是覆盖索引,而不是调参
参数调优是兜底手段,治标不治本。真正根除 Using temporary 的方式,是让 MySQL 能复用索引的物理有序性来完成分组或去重。
- 对
GROUP BY a, b,建联合索引(a, b);若还带WHERE c = ?,优先考虑(c, a, b) -
DISTINCT a, b同样要求所有字段在单个索引中按顺序出现,且不能有函数包裹(如DISTINCT UPPER(name)必走临时表) -
UNION隐含DISTINCT,能用UNION ALL就别用UNION;必须去重时,确保子查询本身已通过索引排好序 - 执行
EXPLAIN前先ANALYZE TABLE更新统计信息,否则优化器可能误判索引可用性
参数再大也填不满设计缺陷——索引没建对,tmp_table_size 设成 1GB 也只是让落盘晚一点,而不是不落盘。


















