MySQL 临时表排查Using temporary 不是一句小提示MySQL 执行计划里的Using temporary经常被当成普通提示但它可能意味着排序、分组或去重过程中需要额外临时表。数据量小的时候不明显数据量上来以后临时表可能落盘查询延迟直接变脸。看到Using temporary不要只皱一下眉就过去。它值得被认真排查。一、临时表从哪里来flowchart TD A[SQL] -- B[GROUP BY] A -- C[ORDER BY] A -- D[DISTINCT] A -- E[UNION] B -- F[Temporary Table] C -- F D -- F E -- F临时表不是一定有问题但它表示执行器需要额外中间结果。是否危险要看数据量、内存阈值和是否落盘。二、先看执行计划和实际执行EXPLAIN SELECT user_id, COUNT(*) FROM orders WHERE created_at 2026-07-01 GROUP BY user_id ORDER BY COUNT(*) DESC;如果 Extra 里出现Using temporary; Using filesort就要继续看实际扫描行数、排序行数和耗时。MySQL 8 可以用EXPLAIN ANALYZE获取更接近真实的执行信息。三、内存临时表和磁盘临时表差很多内存临时表还好落盘后延迟会明显上升。可以看状态变量SHOW GLOBAL STATUS LIKE Created_tmp%;重点关注Created_tmp_disk_tables。如果它随某类查询明显增长说明临时表已经进入磁盘路径。四、优化要从 SQL 形态开始有时可以通过合适索引减少临时表有时需要改写查询把大范围聚合拆到离线任务或汇总表。CREATE INDEX idx_orders_created_user ON orders(created_at, user_id);但索引不是万能。ORDER BY COUNT(*)这类聚合排序本质上仍需要中间结果。不要幻想一个索引解决所有分组排序。还要关注临时表字段类型。包含 TEXT、BLOB 或宽 VARCHAR 的中间结果更容易触发磁盘临时表。查询中如果只需要少数列就不要把宽列带进子查询或派生表。SELECT user_id, COUNT(*) AS cnt FROM ( SELECT user_id FROM orders WHERE created_at 2026-07-01 ) t GROUP BY user_id;这类改写不一定总是更快但能提醒我们中间结果越窄临时表越可控。五、总结MySQLUsing temporary不是一句小提示。它可能来自 group by、order by、distinct、union 等操作关键要看是否落盘、扫描行数和实际耗时。排查时结合EXPLAIN ANALYZE、状态变量和 SQL 形态判断。该加索引就加该改查询就改别把临时表当空气。如果临时表来自业务必需的大范围聚合就该把问题上升到数据模型或报表链路而不是继续在单条 SQL 上拧螺丝。这时更应该考虑汇总表、异步计算或分析库而不是让在线库每天重复做同一批昂贵中间结果。把计算放到合适位置本身就是优化。别让在线查询承担离线报表的重量。