接口突然变慢,第一反应是查数据库。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 开着,定期看,比出事了再查强。

Comments 3 条评论
Using filesort 一出现就得警惕
最左前缀我也栽过
索引列上做函数运算确实废索引