需先配置slow_query_log_file绝对路径并确保MySQL进程有写权限,再用SHOW VARIABLES确认启用状态、路径和阈值;动态开启用SET GLOBAL,永久生效需写入my.cnf。
慢查询分析的前提是日志得真正写进去。很多人配置了 slow_query_log = ON 和 long_query_time = 2,但查不到日志,根本原因是没指定 slow_query_log_file 路径,或者 MySQL 进程对目标目录无写权限。
实操建议:
SHOW VARIABLES LIKE 'slow_query_log%'; 确认三项关键变量:是否启用、日志路径、阈值mysql)可写的绝对路径,例如 /var/log/mysql/mysql-slow.log,不能是相对路径或家目录long_query_time 默认是 10 秒,生产环境建议设为 1.0 或 0.5;注意它只对执行时间 ≥ 阈值的语句生效,不包含锁等待时间(除非开启 log_queries_not_using_indexes)SET GLOBAL slow_query_log = ON;,但重启后失效;永久生效要写进 my.cnf 的 [mysqld] 段mysqldumpslow 是 MySQL 自带的轻量级分析工具,适合快速筛出“最慢的 10 条”或“出现最多的 5 条”,比直接 grep 日志高效得多。
常见组合用法:
mysqldumpslow -s t -t 10 /var/log/mysql/mysql-slow.log:按总执行时间排序,取前 10 条mysqldumpslow -s c -t 5 /var/log/mysql/mysql-slow.log:按出现次数排序,看哪些 SQL 被反复执行mysqldumpslow -g "SELECT.*FROM orders" /var/log/mysql/mysql-slow.log:过滤含特定模式的慢查询(注意正则语法简单,不支持复杂匹配)注意:mysqldumpslow 会自动归一化 SQL(比如把 WHERE id = 123 变成 WHERE id = N),所以统计的是“模板维度”的频次,不是原始语句条数。
Percona Toolkit 的 pt-query-digest 是业界事实标准,它能解析慢日志、聚合统计、识别全表扫描、估算索引收益,还能输出可读报告和优化建议。
典型使用流程:
pt-query-digest /var/log/mysql/mysql-slow.log
pt-query-digest --limit 3 /var/log/mysql/mysql-slow.log
EXPLAIN 分析某类慢查询:pt-query-digest --explain h=127.0.0.1,u=root,p=xxx /var/log/mysql/mysql-slow.log(需确保账号有
PROCESS 权限)pt-query-digest --report-format html /var/log/mysql/mysql-slow.log > slow-report.html
关键点:它默认只分析 Query 类型语句,若日志里有 Connect、Quit 等非查询事件,需加 --filter '$event->{fingerprint} =~ m/^select|^update|^insert|^delete/' 过滤。
这是调优中最常被误判的点——EXPLAIN 输出 type = ALL 表示全表扫描,但未必是“没建索引”,更可能是索引失效或优化器误选。
排查优先级:
WHERE 条件字段是否在索引最左列,比如索引是 (a,b,c),但查询写了 WHERE b = 1,就无法使用该索引user_id 是 INT,但 SQL 写成 WHERE user_id = '123',会导致索引失效key_len 是否符合预期,若远小于索引定义长度,说明只用了部分列ANALYZE TABLE table_name; 更新统计信息,避免优化器因过期数据误判SELECT * FROM t USE INDEX (idx_a_b) WHERE a = 1 AND b = 2;,再对比执行时间真正难调的,往往不

ORDER BY + LIMIT 场景下优化器放弃索引选择文件排序。