show profile 在 mysql 8.0+ 中已被移除,仅适用于 5.7 及更早版本;需先确认版本(select version())和 profiling 开关状态(select @@profiling),开启后执行 sql 并立即用 show profile for query n 分析各阶段耗时,瓶颈常出现在 creating tmp table、sorting result 等阶段;mysql 8.0+ 应改用 performance schema 配合 events_statements_history_long 或慢查询日志定位性能问题。

SHOW PROFILE 在 MySQL 5.7 及更早版本中可用,但自 MySQL 8.0 起已被彻底移除 —— 如果你用的是 8.0+,这条命令直接报错 ERROR 1064 (42000): You have an error in your SQL syntax,别折腾了,换方案。
确认 MySQL 版本和 profiling 开关状态
执行前必须知道两点:你的 MySQL 是不是 5.7 或更老;以及 profiling 是否已开启。它默认是关闭的,且只对当前会话生效。
- 查版本:
SELECT VERSION(); - 查开关:
SELECT @@profiling;(返回 0 表示关) - 开开关:
SET profiling = 1;(注意:重启会话后失效) - 关开关:
SET profiling = 0;
执行 SQL 后立刻查 profile,别等太久
SHOW PROFILE 查的是最近执行的语句,按执行顺序编号(从 1 开始),不指定 ID 就查最后一条。如果你中间又跑了别的语句,原来的 profile 就被覆盖了。
- 跑目标 SQL:
SELECT * FROM orders WHERE created_at > '2025-01-01' LIMIT 100; - 立刻查耗时:
SHOW PROFILE FOR QUERY 1;(假设这是第 1 条) - 查所有历史:
SHOW PROFILES;(列出 Query_ID 和 Duration)
输出里关键列是 Status(阶段名,如 Sending data、Sorting result)和 Duration(秒级,精度到微秒)。耗时最长的阶段就是瓶颈所在。
常见高耗时阶段及对应优化方向
不同阶段暴露的问题类型差异很大,不能只看总时间:
-
Creating tmp table:说明用了临时表,大概率是GROUP BY、ORDER BY非索引字段,或UNION—— 检查是否能加索引或改写查询 -
Copying to tmp table:结果集太大,内存临时表撑不住,转磁盘了 —— 看tmp_table_size和max_heap_table_size配置,但治标不治本,优先缩小结果集 -
Sorting result:排序没走索引 —— 确认ORDER BY字段是否有合适索引,尤其注意联合索引顺序 -
Waiting for query cache lock:说明启用了 query cache(MySQL 5.7 默认开),但并发高时锁争用严重 —— 直接关掉更稳妥:SET GLOBAL query_cache_size = 0;
MySQL 8.0+ 的替代方案:Performance Schema
8.0 之后必须用 performance_schema,虽然配置略麻烦,但数据更细、更可靠。
- 确保启用:
SELECT * FROM performance_schema.setup_consumers WHERE NAME LIKE 'events%';,把相关 consumer 设为YES - 启用收集:
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME = 'statement/sql/select'; - 查最近慢查询:
SELECT EVENT_ID, TRUNCATE(TIMER_WAIT/1000000000000, 6) AS sec, SQL_TEXT FROM performance_schema.events_statements_history_long WHERE SQL_TEXT LIKE 'SELECT%' ORDER BY TIMER_WAIT DESC LIMIT 5;
注意:events_statements_history_long 默认只存 10000 条,高频系统可能被刷掉;真正压测或定位问题时,建议配合 slow_query_log + long_query_time=0 抓全量。











