SQL 如何定位慢 SQL?

定位慢SQL需结合日志、性能视图与业务场景:开启慢查询日志并用mysqldumpslow分析;实时执行SHOW PROCESSLIST或查询performance_schema;对SQL用EXPLAIN看type/key/rows/Extra;再关联业务调用量、数据量变化、锁等待及历史趋势归因

定位慢 SQL 的核心是找出执行时间长、资源消耗高或频繁执行的 SQL 语句,关键在于结合数据库日志、性能视图和实际业务场景来分析。

开启并查看慢查询日志

MySQL 默认不开启慢查询日志,需手动配置。在 my.cnf 中添加:

  • slow_query_log = ON
  • slow_query_log_file = /var/log/mysql/slow.log
  • long_query_time = 1(单位秒,建议设为 0.5~2,根据业务调整)
  • log_queries_not_using_indexes = ON(可选,记录未走索引的查询)

重启 MySQL 后,执行慢的 SQL 会自动写入日志。用 mysqldumpslow 工具快速汇总分析,例如:
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log(按总执行时间排序,取前 10 条)

实时抓取正在运行的慢 SQL

适用于突发性慢查,来不及等日志积累。在 MySQL 中执行:

  • SHOW PROCESSLIST; 查看当前连接和执行中的语句(注意 Time 列是否持续增长)
  • SELECT * FROM information_schema.PROCESSLIST WHERE TIME > 60;(筛选运行超 60 秒的会话)
  • SELECT * FROM performance_schema.events_statements_current WHERE TIMER_WAIT > 1000000000000;(单位皮秒,约 1 秒,需确保 performance_schema 开启)

分析执行计划(EXPLAIN)

对疑似慢 SQL 执行 EXPLAIN,重点关注:

  • type:尽量为 constrefrange;避免 ALL(全表扫描)
  • key:是否命中预期索引;为 NULL 表示未使用索引
  • rows:预估扫描行数,远大于结果集时说明过滤效率低
  • Extra:出现 Using filesortUsing temporary 往往意味着排序/分组没走索引

结合业务与监控做归因

单条 SQL 慢不等于问题根源,要关联上下文:

  • 检查该 SQL 是否在高峰期被高频调用(如首页接口每秒数百次)
  • 确认数据量是否突增(例如订单表从百万升至千万,原索引失效)
  • 观察锁等待情况:SELECT * FROM information_schema.INNODB_TRX;INNODB_LOCK_WAITS
  • 比对历史执行时间趋势(通过 Prometheus + Grafana 或阿里云 DMS 等工具)