慢查询日志是MySQL提供的一种记录SQL执行情况的诊断工具,当某条SQL语句的执行时间超过预设阈值时,该语句的完整信息会被写入日志文件。通过分析这些日志,可以直观地看到哪些查询消耗了大量时间、扫描了过多数据行,进而为索引优化、SQL改写和参数调整提供事实依据。与盲目猜测性能瓶颈相比,基于慢查询日志的分析路径更加系统且可靠。

一、慢查询日志的开启与关键参数配置
慢查询日志默认在MySQL中是关闭的,或者记录阈值设置得很高,导致无法捕捉到真实问题。开启慢查询日志通常需要调整以下几个核心参数:slow_query_log控制日志总开关;long_query_time定义SQL执行超过多少秒才被记录;slow_query_log_file指定日志文件路径;log_output决定日志输出到文件还是表;log_queries_not_using_indexes可以记录那些没有使用索引的查询。对于生产环境,建议使用文件输出并独立存储,避免日志写表带来的额外开销。
可以通过SET GLOBAL命令在线修改,但重启后失效,永久生效需要写入配置文件。下面是一个典型的配置示例:
[mysqld] slow_query_log = 1 slow_query_log_file = /var/log/mysql/slow.log long_query_time = 1 log_queries_not_using_indexes = 1 log_output = FILE
需要注意的是,long_query_time设为1秒表示超过1秒才会记录,如果希望捕捉几百毫秒的慢查询,可以设置为0.5。但阈值过低会导致日志量激增,增加I/O压力。另外,log_queries_not_using_indexes开启后,即使SQL执行时间未超过阈值,只要没有使用索引也会被记录下来,这在优化早期非常有用,但也会产生较多日志。建议在低峰期开启并配合日志轮转。
二、慢查询日志字段详解与阅读方法
慢查询日志中每条记录包含多个关键字段,理解这些字段的含义是分析工作的基础。典型的慢查询日志片段如下:
# Time: 2025-04-08T10:23:45.123456Z # User@Host: root[root] @ localhost [127.0.0.1] # Query_time: 3.204512 Lock_time: 0.000234 Rows_sent: 10 Rows_examined: 100000 SET timestamp=1744111425; SELECT * FROM orders WHERE user_id = 100 AND status = 'pending' ORDER BY create_time DESC LIMIT 10;
其中Query_time表示该SQL执行的总耗时,Lock_time表示等待锁的时间,Rows_sent是返回给客户端的行数,Rows_examined是引擎层实际扫描的行数。重点关注Rows_examined与Rows_sent的比值:如果扫描了100000行却只返回10行,说明SQL大概率缺少合适索引或过滤条件不够精准。Lock_time过高则提示可能存在锁竞争,需要进一步检查事务隔离级别和表锁情况。User@Host字段可以定位到发起查询的应用来源,便于追溯业务模块。
阅读日志时还应关注同一条SQL出现的频率。如果某条查询单次执行耗时只有0.8秒,但每分钟调用上百次,累积消耗同样惊人。手工统计日志比较繁琐,此时可以借助工具自动聚合分析。另外,日志中的SET timestamp语句是为了在回放时保持时间一致性,分析时可忽略。
三、使用mysqldumpslow和pt-query-digest高效分析
对于小规模日志,可以直接用文本编辑器查看,但当日志文件达到几十甚至上百MB时,手工分析几乎不可能完成。MySQL官方自带的mysqldumpslow工具可以快速汇总慢查询,按执行次数、总耗时、锁定时间等维度排序。常用的选项包括:-s指定排序方式(c为次数,t为总时间,l为锁时间,r为返回行数),-t指定输出前N条,-g支持正则过滤。例如以下命令按执行次数输出Top 10:
mysqldumpslow -s c -t 10 /var/log/mysql/slow.log
mysqldumpslow的缺点是统计粒度较粗,无法展示SQL的具体执行计划,也不具备指纹分析能力。更强大的工具是Percona Toolkit中的pt-query-digest。它能够对慢查询日志进行指纹归一化,把参数值不同的同类SQL聚合成一条摘要,并生成详细报告。报告中包含每条查询的执行次数、时间分布、Explain信息、索引建议等。基本用法如下:
pt-query-digest /var/log/mysql/slow.log > slow_report.txt
pt-query-digest生成的报告将查询按总耗时降序排列,并给出每个查询的响应时间剖面图、主要来源主机、最慢执行实例等。阅读报告时优先关注总耗时占比高的前几条SQL,这些通常是优化的主要目标。如果pt-query-digest安装受限,也可以使用Percona的在线版本或直接基于慢日志表自写脚本聚合,但工作量和准确性不如现成工具。
四、从慢查询到性能优化:实战案例与建议
假设经过分析发现一条慢查询如下:SELECT * FROM orders WHERE user_id = 100 AND status = 'pending' ORDER BY create_time DESC LIMIT 10,其Rows_examined达到100000,Rows_sent仅为10,Query_time超过3秒。通过EXPLAIN查看执行计划:
EXPLAIN SELECT * FROM orders WHERE user_id = 100 AND status = 'pending' ORDER BY create_time DESC LIMIT 10;
执行计划显示type为ALL或index,key列为NULL或者虽然走了user_id单列索引但仍然需要额外排序和过滤。针对该场景,最优方案是建立覆盖索引(user_id, status, create_time),这样查询既能精准过滤,又能利用索引的有序性避免文件排序,同时若需要返回的列较少,可以进一步改写为覆盖索引查询,减少回表。示例优化语句如下:
ALTER TABLE orders ADD INDEX idx_user_status_create (user_id, status, create_time);
除了加索引,还需要检查SQL写法是否可以优化。例如避免在WHERE条件中对字段使用函数,避免使用SELECT *而只取需要的列,拆分大事务和复杂子查询。如果Rows_examined已经很小但Query_time仍然很高,可能需要关注网络延迟、磁盘I/O、锁等待或CPU饱和等系统层面的问题。此时结合InnoDB状态、SHOW PROCESSLIST以及操作系统监控进一步排查。
最后,慢查询日志分析不是一次性的工作,而应纳入日常运维流程。可以定期对慢日志进行趋势分析,观察优化前后同一SQL的执行时间变化,验证改动效果。同时,设置合理的日志轮转和保留策略,避免日志文件无限增长影响磁盘空间。通过持续分析、优化、验证的闭环,数据库的整体响应能力会逐步提升。
MySQL慢查询日志慢查询分析SQL性能优化修改时间:2026-08-27 16:54:25