慢查询日志是定位问题SQL的起点,需正确配置阈值、用mysqldumpslow分析日志、通过EXPLAIN验证执行计划、结合索引设计与SQL改写协同优化,形成闭环。

慢查询日志不是“开了就能自动变快”的开关,而是精准定位问题SQL的起点。真正有效的优化,必须从日志配置开始,经由日志分析、执行计划解读,最终落到索引设计和SQL改写上——每一步都环环相扣,缺一不可。
一、正确开启并确认慢查询日志
很多问题卡在第一步:日志根本没开,或开了但阈值不合理。生产环境建议设为1秒(甚至0.5秒),而不是默认的10秒。
- 临时开启(立即生效,重启失效):
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 = 1slow_query_log_file = /var/log/mysql/slow.loglong_query_time = 1log_queries_not_using_indexes = 1 - 验证是否生效:
SHOW VARIABLES LIKE 'slow_query_log';SHOW VARIABLES LIKE 'long_query_time';SHOW VARIABLES LIKE 'slow_query_log_file';
二、高效解析慢日志,快速锁定“真凶”
手动翻日志效率极低。MySQL自带mysqldumpslow是首选工具,不用额外部署。
- 按总耗时排序Top 10:
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log - 按执行次数排序Top 10:
mysqldumpslow -s c -t 10 /var/log/mysql/slow.log - 重点关注
Query_time(实际耗时)、Rows_examined(扫描行数)——如果扫描几十万行只返回几条,基本就是索引缺失或失效 - 注意
Lock_time偏高,可能暗示锁竞争,需结合information_schema.innodb_lock_waits进一步排查
三、用 EXPLAIN 看懂执行逻辑,不靠猜
加了索引却没生效?EXPLAIN 是唯一可信依据。关键字段就三个:
-
type:至少要达到
range,理想是ref或eq_ref;出现ALL就是全表扫描,必须处理 -
key:显示实际使用的索引名。若为
NULL,说明没走索引(哪怕建了) -
rows:MySQL预估扫描行数。数值越大,越需警惕;与
Rows_examined接近才可信 - Extra里出现
Using filesort或Using temporary,说明排序或分组没走索引,需优化ORDER BY或GROUP BY字段
四、索引与SQL协同优化,避免“单点修补”
加索引不是万能解药,必须配合SQL写法。常见组合策略:
- 联合索引严格遵循最左前缀:比如
(a,b,c),WHERE中含a=1 AND b=2可用,但b=2 AND c=3不可用 - 覆盖索引减少回表:SELECT只查索引已包含的字段,例如
SELECT id,status FROM orders WHERE user_id=123,可建INDEX(user_id, status, id) - 避免索引失效操作:
— 字段上做函数:WHERE DATE(create_time) = '2026-07-06'→ 改为WHERE create_time BETWEEN '2026-07-06 00:00:00' AND '2026-07-06 23:59:59'
— 隐式类型转换:user_id VARCHAR却传整型值 → 统一数据类型
— 前导%模糊:LIKE '%abc'无法走索引,考虑全文索引或倒排表 - 分页优化:
LIMIT 100000, 20应改用延迟关联:SELECT * FROM orders JOIN (SELECT id FROM orders WHERE status=1 ORDER BY id LIMIT 100000, 20) AS tmp USING(id);
不复杂但容易忽略:每次加索引或改SQL后,务必用EXPLAIN再验证一次,确保优化真正落地。性能优化不是一次性动作,而是配置、观察、分析、调整的闭环过程。


















