show profile 不会直接显示是否使用索引,但能揭示索引扫描的真实瓶颈,如 handler_read_next 长、creating sort index 占比高或 copying to tmp table 突增,这些才是索引高效与否的关键信号。

直接说结论:Show Profile 不会告诉你“是不是用了索引”,但它能暴露索引扫描阶段的真实耗时瓶颈,比如 handler_read_next 长、Creating sort index 占比高、或 Copying to tmp table 突然飙升——这些才是索引是否被高效利用的关键信号。
确认 profiling 功能已启用且生效
很多问题根本没走到分析环节,就卡在开关没打开。别只查 @@have_profiling,它只表示编译支持,不等于可用。
-
SELECT @@profiling必须返回1,否则SHOW PROFILES一定为空 -
SET profiling = 1只对当前 session 生效,新开连接要重设 -
SELECT @@profiling_history_size默认是 15,如果执行了太多语句,早期的 query_id 会被覆盖,查不到想看的那条 - 注意:MySQL 8.0.22+ 已弃用 profiling,官方推荐用
performance_schema替代;但 5.7 和 8.0 早期版本仍广泛依赖它
执行带索引条件的 SQL 后立即抓取 profile 数据
不能等、不能缓存、不能复用结果——SHOW PROFILE 查的是上一条语句(或指定 FOR QUERY n),而 EXPLAIN 看的是预估执行计划,两者必须配对使用才有意义。
- 先跑一次
EXPLAIN SELECT * FROM tb_user WHERE name = '白起',确认type是ref或range,key显示用了哪个索引 - 再立刻执行同一条
SELECT * FROM tb_user WHERE name = '白起'(不要加EXPLAIN) - 马上执行
SHOW PROFILES找到对应Query_ID,再用SHOW PROFILE FOR QUERY n查细节 - 避免在语句后加
ORDER BY或LIMIT改变执行路径;如果业务真需要,就按真实场景执行,而不是“为分析而简化”
重点盯住这几个 Status 行,它们直接反映索引使用质量
不是所有耗时都值得优化,要聚焦在和索引遍历、排序、临时表强相关的阶段:
-
handler_read_next:B+Tree 索引逐行读取的次数。值越大,说明索引扫描范围越宽(比如用了前缀索引但匹配度低,或WHERE条件过滤性差) -
Creating sort index:MySQL 在内存或磁盘上建排序索引。出现这个,大概率是ORDER BY列没包含在联合索引里,或索引顺序不匹配 -
Copying to tmp table:触发了隐式临时表(常见于GROUP BY、DISTINCT、UNION)。即使走了索引,也可能因无法覆盖查询字段而回表+建临时表 -
statistics阶段耗时异常高:说明优化器花了大量时间估算成本,可能因为统计信息过期(ANALYZE TABLE没跑)或存在大量数据倾斜
对比有无索引的 profile 差异,而非只看总耗时
总耗时下降 90% 不代表索引设计合理——可能只是数据量小、缓存命中率高。真正要看的是各阶段耗时结构的变化。
- 删掉索引后跑一次相同 SQL 的
SHOW PROFILE FOR QUERY n,对比handler_read_next是否从几百跳到几万(全表扫描的代价) - 加了索引但
Creating sort index耗时反而上升?说明索引列顺序没对齐ORDER BY,比如建了(a,b)却按b排序 -
Using where出现在Extra中,但 profile 里checking permissions或init耗时长,可能是权限校验或视图解析拖慢了启动阶段,和索引无关
Profile 给出的是“发生了什么”,不是“为什么发生”。它不会告诉你 name 字段该不该加前缀,也不会指出联合索引缺了哪一列——这些必须结合 EXPLAIN 的 key_len、rows、filtered 和业务查询模式一起判断。忽略这点,光盯着 Duration 数字调优,很容易南辕北辙。











