SQL慢查询日志如何正确开启与分析?

来源:我的博客作者:清原小日向头衔:网络博主
导读:本期聚焦于小伙伴创作的《SQL慢查询日志如何正确开启与分析?》,敬请观看详情。数据库响应变慢时,多数问题藏在那些执行时间过长的SQL里。慢查询日志就是把这些语句按执行耗时记录下来供排查的功能。在MySQL中,该能力默认关闭,需手动开启并设置阈值。阈值通过long_query_time控制,单位秒,设为0.5即记录超过半秒的语句。除阈值外,未走索引的查询也可通过log_queries_not_using_indexes记入日志。分析阶段不能只盯耗时,还要结合扫描行数、返回行数以及执行频率判断。直接翻日志文件效率低,用mysqldumpslow或pt-query-digest归类统计更实用。掌握开启参数与分析方法,才能把数据库性能问题真正定位到具体语句上。

SQL慢查询日志是数据库自带的审计机制,用来记录执行时间超过指定阈值或者未使用索引的SQL语句。通过它,开发者和DBA能够把性能瓶颈从模糊的“数据库慢”缩小到某几条具体的查询上。不同数据库的实现略有差异,本文以最常见的MySQL为例说明完整的开启与分析流程。

SQL慢查询日志如何正确开启与分析?

一、慢查询日志的开启方式

MySQL的慢查询日志受多个系统变量控制,最核心的是slow_query_logslow_query_time以及log_output。默认情况下slow_query_log的值为OFF,也就是说日志功能处于关闭状态。我们可以通过命令行动态修改,也可以写进配置文件实现永久生效。

动态开启适合临时排查,不需要重启数据库实例。在MySQL客户端中执行下列语句即可:

-- 开启慢查询日志
SET GLOBAL slow_query_log = 'ON';
-- 设置慢查询阈值为0.5秒
SET GLOBAL long_query_time = 0.5;
-- 将日志输出到文件
SET GLOBAL log_output = 'FILE';
-- 指定日志文件路径
SET GLOBAL slow_query_log_file = '/var/lib/mysql/slow.log';

上述参数中,long_query_time的单位是秒,支持小数点后精度。如果设置为0,则所有查询都会被记录,这在极端调试场景下有用,但会带来大量磁盘写入,生产环境应避免。为了让配置在数据库重启后依然有效,应当修改MySQL配置文件(如my.cnf或my.ini):

[mysqld]
slow_query_log = 1
slow_query_log_file = /var/lib/mysql/slow.log
long_query_time = 0.5
log_queries_not_using_indexes = 1

其中log_queries_not_using_indexes表示即便查询未超过时间阈值,只要没有使用索引也记入日志。这个选项能帮助我们提前发现潜在的全表扫描问题。修改配置文件后需重启MySQL服务才能生效,使用systemctl restart mysqld或对应平台的命令即可。

二、日志内容结构解析

一条典型的慢查询日志包含查询时间、执行耗时、锁等待时间、发送行数、扫描行数以及具体的SQL文本。理解这些字段是后续分析的基础。下面是一段经过简化的日志样例:

# Time: 2023-08-12T10:22:01.123456Z
# User@Host: app[app] @ 192.168.0.1 []
# Query_time: 2.341234  Lock_time: 0.000123
# Rows_sent: 10  Rows_examined: 982341
SELECT * FROM orders WHERE user_id = 123 AND status = 'paid' ORDER BY created_at DESC LIMIT 10;

Query_time是语句从开始到结束的总耗时,Lock_time是等待表锁的时间。如果Lock_time接近Query_time,说明瓶颈在锁竞争而非SQL本身。Rows_examined代表存储引擎扫描的行数,而Rows_sent是返回给客户端的行数。当Rows_examined远大于Rows_sent时,通常意味着缺少合适的索引或写了不够精确的过滤条件。

除了上述基础字段,MySQL还可在日志中记录更详细的信息,例如通过log_slow_extra输出线程ID、事务ID等。对于复杂系统,建议结合应用层的trace_id,在SQL注释中带上标识,这样能从慢日志反查到具体业务请求。例如:SELECT /* trace_abc123 */ * FROM orders ...,这种写法不影响执行计划,却极大方便了跨系统排查。

三、慢查询的分析工具与方法

直接用人眼翻阅原始日志效率极低,尤其当日志达到几万行时。MySQL自带了mysqldumpslow工具,可以按不同维度汇总相似的SQL。常见用法如下:

# 按平均查询时间排序,取前10条
mysqldumpslow -s at -t 10 /var/lib/mysql/slow.log

# 按总耗时排序
mysqldumpslow -s t -t 10 /var/lib/mysql/slow.log

# 不将数字和字符串抽象为N和S,方便看具体值
mysqldumpslow -a -s c /var/lib/mysql/slow.log

-s参数指定排序方式,c是执行次数,t是总耗时,at是平均耗时。通过归类,我们能快速找到“执行次数多且平均慢”的语句,这类语句往往比偶发性的超级慢查询更值得优化。另一个更强大的开源工具是Percona的pt-query-digest,它能生成包含响应时间分布、索引建议的详细报告。

在分析时,不要只盯着Query_time。一条SQL如果每次只慢0.1秒但每秒执行200次,对数据库的压力远大于一条偶尔跑5秒的报表查询。因此要把Rows_examined和执行频率放在一起看。优化手段通常包括:为WHERE和ORDER BY字段建立联合索引、避免SELECT *、把子查询改写为JOIN、利用覆盖索引减少回表。下例展示了一个缺少索引的慢查询及其优化:

-- 原始慢SQL,orders表在user_id上无索引
SELECT id, amount FROM orders WHERE user_id = 123 AND status = 'paid';

-- 增加联合索引后的DDL
ALTER TABLE orders ADD INDEX idx_user_status (user_id, status);

建立索引后,存储引擎可直接定位到匹配的行,Rows_examined从全表量级降到个位数,查询耗时会呈数量级下降。但要注意索引并非越多越好,写操作会因为维护索引变慢,需权衡读写比例。

四、常见误区与注意事项

不少团队在开启慢查询日志后,把long_query_time设得过大,比如5秒,结果大量1到2秒的“中速查询”被漏掉,用户依然反馈卡顿。一般Web接口建议阈值设在0.1到0.5秒之间,这样才能捕获影响体验的语句。另外,开启log_queries_not_using_indexes时要小心,若某小表本就只有几百行,全表扫描比走索引更快,这类记录会污染日志,可配合min_examined_row_limit忽略扫描行数过少的查询。

还有一点容易被忽视:慢查询日志本身会消耗磁盘IO。在高并发写入场景,建议将日志放到独立磁盘,并定期用脚本归档清理。对于云数据库,通常控制台已提供慢查询分析面板,底层也是同一套机制,但省去了自建采集的麻烦。无论用哪种方式,核心逻辑不变,就是先让慢语句显形,再用索引和执行计划(EXPLAIN)验证优化效果,形成闭环。

五、结合EXPLAIN做深度验证

从日志里拿到可疑SQL后,应在测试环境用EXPLAIN查看执行计划。重点观察type列,若出现ALL表示全表扫描;key列显示实际使用的索引;rows列是预估扫描行数,应与日志中的Rows_examined对照。示例如下:

EXPLAIN SELECT id, amount FROM orders WHERE user_id = 123 AND status = 'paid';

如果key为NULL且type为ALL,证明索引未生效,需检查字段类型是否一致(如字符串字段用了数字比较)、是否对字段使用了函数导致索引失效。把EXPLAIN结果和慢日志字段交叉比对,能避免凭直觉优化而忽略真实执行路径,从而让每一次调整都落在真正的瓶颈上。

slow_query_logSQL优化查询分析修改时间:2026-08-01 19:33:43

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。