
定位SQL慢查询,核心是“先看日志,再查计划”——慢日志帮你找到“哪条SQL慢”,执行计划告诉你“为什么慢”。两者结合,才能精准定位性能瓶颈,避免盲目优化。
开启并确认慢查询日志是否生效
慢日志是分析起点,没开就无从谈起。需确认三件事:是否启用、阈值设置是否合理、日志是否真实写入。
- 执行 SHOW VARIABLES LIKE 'slow_query_log' 查看是否为 ON
- 用 SHOW VARIABLES LIKE 'long_query_time' 检查阈值(默认1秒,线上建议调至0.1~0.5秒)
- 运行 SELECT SLEEP(2) 触发一次慢操作,再检查慢日志文件(路径由 slow_query_log_file 变量指定)是否有新增记录
从慢日志中高效提取可疑SQL
慢日志内容冗长,重点抓取执行时间长、扫描行数多、锁等待久的语句。注意过滤干扰项(如备份、监控探针产生的慢SQL)。
- 用 mysqldumpslow 工具聚合分析(例如:mysqldumpslow -s t -t 10 /var/log/mysql/slow.log 按耗时排前10)
- 手动查看时关注字段:# Query_time(实际执行耗时)、Rows_examined(扫描行数)、Lock_time(锁等待时间)
- 对 Rows_examined 远大于 Rows_sent 的SQL要高度警惕——大概率存在全表扫描或索引失效
用EXPLAIN分析执行计划的关键指标
拿到慢SQL后,在测试环境执行 EXPLAIN FORMAT=TRADITIONAL [SQL],重点关注以下几列:
- type:越靠前越好(system ≈ const > eq_ref > ref > range > index > ALL),出现 ALL 表示全表扫描
- key 和 key_len:是否命中索引?命中哪个索引?长度是否合理(比如 varchar(255) 只用前100字符建索引,key_len偏小可能说明没充分利用)
- rows:MySQL预估扫描行数,若远高于实际结果集,说明统计信息过期,可执行 ANALYZE TABLE 更新
- Extra:出现 Using filesort 或 Using temporary 是典型性能红灯,通常意味着排序/分组未走索引
关联慢日志与执行计划做归因判断
单看执行计划可能误判,必须对照慢日志中的实际表现。例如:
- 慢日志显示 Query_time: 3.2s, Rows_examined: 856200,但 EXPLAIN 显示 rows=1200 → 很可能是数据分布倾斜或索引选择错误,需加 FORCE INDEX 验证
- 慢日志中同一类SQL(如带不同用户ID的查询)反复出现,但只有部分很慢 → 检查该字段上是否有索引,以及值分布是否均匀(如 status=0 占99%,status=1 占1%,后者走索引更有效)
- SQL本身简单(如单表主键查询),但 Lock_time 高 → 问题不在SQL结构,而在并发冲突或事务持有锁太久,需查 SHOW ENGINE INNODB STATUS
不复杂但容易忽略:慢日志记录的是“客户端发起请求到服务端返回结果”的总耗时,而EXPLAIN只反映优化器阶段的执行策略。两者结合,才能区分是SQL写法问题、索引缺失、统计不准、还是系统资源或锁竞争导致的延迟。










