mysql如何通过执行流程分析慢SQL_性能排查思路说明

来源:这里教程网 时间:2026-02-28 20:44:00 作者:

怎么看执行计划(EXPLAIN 输出关键字段)

MySQL 的

EXPLAIN
是分析慢 SQL 最直接的入口,但很多人只看
type
rows
,漏掉真正致命的信号。重点盯住这几个字段:

type
:出现
ALL
index
说明全表/全索引扫描,尤其
ALL
在大表上基本等于慢 SQL 定义;
range
算可控,
ref
/
eq_ref
才算走了有效索引
key
:显示实际用到的索引名。为
NULL
就代表没走索引——别急着怪 SQL 写法,先确认该列是否真的有索引、索引顺序是否匹配
WHERE
条件
Extra
:最危险的是
Using filesort
Using temporary
,意味着排序或分组无法利用索引完成,必须额外内存或磁盘操作;
Using index
是好现象(覆盖索引),
Using index condition
表示用了 ICP(索引条件下推)

为什么加了索引还是没走(常见索引失效场景)

索引存在 ≠ 被使用。以下写法会让优化器主动放弃索引:

对索引列做函数操作:
WHERE YEAR(create_time) = 2024
→ 改成
WHERE create_time >= '2024-01-01' AND create_time 
隐式类型转换:
user_id
INT
,但写成
WHERE user_id = '123'
→ 字符串触发类型转换,索引失效
LIKE 左模糊:
WHERE name LIKE '%abc'
→ 无法使用 B+Tree 索引的有序性;
LIKE 'abc%'
可以
联合索引顺序错位:
INDEX(a,b,c)
,查询条件只有
WHERE b = 1
WHERE b = 1 AND c = 2
→ 无法命中该索引(最左前缀不满足)

如何模拟真实负载看执行流程(不只是单条 EXPLAIN)

EXPLAIN
只是预估,实际执行可能因数据分布、缓存、并发而不同。要验证真实行为,得结合:

开启慢日志并设置合理阈值:
SET GLOBAL slow_query_log = ON; SET GLOBAL long_query_time = 1;
,再查
slow_log
表或日志文件,确认是否真被记录
SHOW PROFILE
看各阶段耗时:
SET profiling = 1;
SELECT ... ; -- 你的慢 SQL
SHOW PROFILES;
SHOW PROFILE FOR QUERY 1;
重点关注
Sorting result
Closing tables
Sending data
这些阶段是否异常高
检查锁等待:
SELECT * FROM performance_schema.events_statements_current WHERE SQL_TEXT LIKE '%你的SQL%';
配合
sys.innodb_lock_waits
视图看是否卡在行锁上

ORDER BY 和 GROUP BY 怎么避免 filesort / temporary

这两个操作最容易触发临时表和文件排序,性能杀手。核心原则:让排序/分组字段落在同一个索引的后缀位置,并且顺序一致。

ORDER BY a, b
→ 索引要建为
INDEX(a, b)
,不能是
INDEX(b, a)
,也不能只建
INDEX(a)
GROUP BY a, b ORDER BY a, b
→ 同样需要
INDEX(a, b)
;如果还带
LIMIT
,索引能极大提升效率
注意 ASC/DESC 混用:
ORDER BY a ASC, b DESC
在 MySQL 8.0 之前无法用单一索引优化(需分开建两个方向索引),8.0+ 支持
INDEX(a ASC, b DESC)
如果业务允许,把
GROUP BY
提前聚合(比如用物化视图或定时汇总表),比实时计算安全得多

真实线上环境里,

EXPLAIN
显示“走了索引”但响应仍慢,大概率是
rows
估算严重偏差(统计信息过期)、或者
Using filesort
占据了大部分时间——这两点最容易被忽略。

相关推荐