服务器 mysql 慢查询如何排查 精华
学完这篇,你能独立定位一条 MySQL 慢查询卡在哪一步,并给出可落地的优化动作。
第一步:确认慢查询日志开着,并拿到日志文件
MySQL 默认不记录慢查询,先确认状态。登录后执行:
SHOW VARIABLES LIKE 'slow_query_log';
SHOW VARIABLES LIKE 'long_query_time';
SHOW VARIABLES LIKE 'slow_query_log_file';
如果 slow_query_log 是 OFF,临时开启(重启失效):
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/lib/mysql/slow.log
long_query_time = 1
log_queries_not_using_indexes = 1
改完 systemctl restart mysqld(或 service mysql restart)。做完这一步,你能在 slow_query_log_file 指定的路径看到慢查询记录。
注意:
long_query_time单位是秒,可以写小数如0.5;SET GLOBAL只影响新连接,已有连接仍用旧值。生产库开log_queries_not_using_indexes会写入大量日志,建议只在排查期临时开。
第二步:从日志里找出「最值得优化」的那几条
日志会很长,别一条条看。两种工具:
mysqldumpslow(MySQL 自带):
mysqldumpslow -s t -t 10 /var/lib/mysql/slow.log
-s t 按总耗时排序,-t 10 取前 10 条。还可以 -s c 按出现次数排序,找高频慢 SQL。
pt-query-digest(Percona Toolkit,分析更细):
pt-query-digest /var/lib/mysql/slow.log
输出里有 Query ID、Response time 占比、Rows examine 与 Rows sent 的比例,比例悬殊说明扫了太多行、索引没用上。做完这一步,你手上应该只剩 1~3 条待分析的 SQL。
第三步:用 EXPLAIN 看执行计划
拿到具体 SQL 后,在它前面加 EXPLAIN:
EXPLAIN SELECT * FROM orders WHERE user_id = 10086 AND status = 1;
重点看四个字段:
type:出现ALL是全表扫描,index是全索引扫描,都不理想;ref、range、eq_ref才算正常。key:实际用的索引,为NULL说明没走索引。rows:预估扫描行数,越大越危险。Extra:出现Using filesort(额外排序)、Using temporary(临时表)通常就是性能杀手。
MySQL 8.0 可以用 EXPLAIN ANALYZE SELECT ... 看真实执行耗时和实际行数,和预估行数对比能发现统计信息偏差。
注意:
EXPLAIN ANALYZE会真正执行语句,在几十万行以上的表上跑,先加LIMIT或到从库执行。
第四步:对照索引做优化
用 SHOW INDEX FROM orders; 看现有索引。常见问题与动作:
- 没索引:对
WHERE、JOIN ON、ORDER BY涉及的列建索引,例如ALTER TABLE orders ADD INDEX idx_user_status (user_id, status); - 组合索引顺序不对:遵循最左前缀原则,把区分度高(唯一值多)的列放前面,
SHOW INDEX里Cardinality越大越靠前。 - 索引失效:
WHERE里对索引列做了函数运算(如DATE(created_at) = '2024-01-01')、隐式类型转换(字符串列传数字)、LIKE '%xx'前置通配,都会让索引失效,改写 SQL 而不是加索引。 - 回表太多:查询只需要少数几列时,把这几列加进索引做覆盖索引,让
Extra出现Using index。
第五步:确认是不是被锁或并发拖慢的
如果单条 SQL 单独跑很快,线上却慢,查实时状态:
SHOW FULL PROCESSLIST;
SELECT * FROM sys.innodb_lock_waits;
SHOW ENGINE INNODB STATUS\G
State 长时间停在 Waiting for table metadata lock 或 Sending data,说明瓶颈在锁等待或大量数据读取,不是索引问题。
小结
- 排查链路是:开慢日志 → 聚合排序找重点 →
EXPLAIN看执行计划 → 对照索引改 SQL/加索引 → 必要时查锁与并发。 - 优先看
type、key、rows、Extra四个字段,别通读日志。 - 索引优化遵守最左前缀,注意函数运算和隐式转换导致的失效。
EXPLAIN ANALYZE会执行语句,生产环境慎用,可先上从库。
原文链接:https://www.gj0.com/thread-539.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。