定位慢SQL需先开启慢查询日志并用pt-query-digest分析,再通过EXPLAIN检查执行计划,结合Performance Schema实时监控,最后关联系统指标判断瓶颈。

定位慢 SQL 是 MySQL 性能排查中最常见也最关键的一步。核心思路是:先找到“谁慢”,再分析“为什么慢”。不靠猜,靠日志、指标和执行计划。
开启并查看慢查询日志
慢查询日志是定位问题的第一手依据。默认通常关闭,需手动启用:
- 在 my.cnf 中添加:slow_query_log = ON,slow_query_log_file = /var/log/mysql/slow.log,long_query_time = 1(单位秒,建议设为 0.5~2,根据业务调整)
- 动态开启(无需重启):SET GLOBAL slow_query_log = ON;,SET GLOBAL long_query_time = 1;
- 注意:log_queries_not_using_indexes = ON 可额外记录未走索引的查询,但生产环境慎开,日志量可能激增
用 pt-query-digest 快速分析慢日志
原生日志可读性差,推荐用 Percona Toolkit 的 pt-query-digest 做聚合分析:
- 命令示例:pt-query-digest /var/log/mysql/slow.log --limit 10,输出按响应时间、执行次数排序的 Top SQL
- 关键看三列:Rank(影响排名)、Query_time(总耗时占比)、Rows_examined(扫描行数)——高 Rows_examined 往往意味着缺失索引或索引失效
- 它还能生成报告 HTML,带执行计划摘要和样例语句,适合团队共享
对慢 SQL 手动分析执行计划(EXPLAIN)
拿到具体 SQL 后,用 EXPLAIN FORMAT=TRADITIONAL 或 EXPLAIN ANALYZE(MySQL 8.0.18+)看真实执行路径:
- 重点关注:type(是否用到高效访问类型,如 const/ref;避免 ALL/index)、key(实际使用的索引)、rows(预估扫描行数,远大于返回行数就危险)、Extra(警惕 Using filesort、Using temporary、Using join buffer)
- 常见陷阱:WHERE 子句中对字段做函数操作(如 YEAR(create_time) = 2024)会跳过索引;联合索引顺序错(如索引是 (a,b),却只查 b);隐式类型转换(如字符串字段 vs 数字参数)导致索引失效
结合 Performance Schema 实时抓取活跃慢查询
当慢日志来不及捕获或想看“正在发生”的问题时,Performance Schema 更及时:
- 开启相关消费者:UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE '%statements%';
- 查当前执行超时的语句:SELECT * FROM performance_schema.events_statements_current WHERE TIMER_WAIT > 1000000000000 LIMIT 5;(1e12 纳秒 = 1 秒)
- 配合 events_statements_history_long 可回溯最近几百条慢语句,适合突发抖动场景
不复杂但容易忽略:别只盯着单条 SQL,要结合 QPS、连接数、InnoDB 状态(如 SHOW ENGINE INNODB STATUS)判断是孤立问题还是系统性瓶颈。定位慢 SQL 是起点,优化才是闭环。











