MySQL 慢查询定位:从 slow log 到 explain

Cold 发布于 2019-03-27 34 次阅读 327 字 预计阅读时间: 1 分钟 后端开发


接口突然变慢,第一反应是查数据库。MySQL 的慢查询日志是最直接的入口。

开启慢查询日志

-- 查看当前配置
SHOW VARIABLES LIKE 'slow_query%';
SHOW VARIABLES LIKE 'long_query_time';

-- 临时开启(重启失效)
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
SET GLOBAL log_queries_not_using_indexes = 'ON';

永久生效改 my.cnf:

[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
log_queries_not_using_indexes = 1

用 mysqldumpslow 分析

# 按出现次数排序,取前 10
mysqldumpslow -s c -t 10 /var/log/mysql/slow.log

# 按平均耗时排序
mysqldumpslow -s at -t 10 /var/log/mysql/slow.log

EXPLAIN 看执行计划

EXPLAIN SELECT * FROM orders WHERE user_id = 123 AND status = 1 ORDER BY created_at DESC LIMIT 20;

重点看几列:

  • type:ALL 全表扫描最差,至少要 range,ref/eq_ref 较好
  • key:实际用的索引,NULL 表示没走索引
  • rows:预估扫描行数,越大越慢
  • Extra:出现 Using filesort、Using temporary 要警惕

常见优化方向

  • 加联合索引,注意最左前缀
  • 避免在索引列上做函数运算,如 WHERE DATE(created_at) = '2019-03-01'
  • 分页深翻用游标或延迟关联
  • 子查询改 JOIN
  • 避免 SELECT *,减少回表

慢查询治理是个持续活,上线前把 slow log 开着,定期看,比出事了再查强。

和喜欢的一切在一起~
最后更新于 2019-03-27