SQL慢查询日志开启后如何快速定位高频SQL

来源:网络学院作者:高永康头衔:资深程序员
导读:本期聚焦于小伙伴创作的《SQL慢查询日志开启后如何快速定位高频SQL》,敬请观看详情。慢查询日志把执行时间超阈值的SQL都记下来,但原始文件里零散的语句很难看出哪些最耗费资源。直接翻文本不仅费眼,还容易漏掉重复模板。借助Percona Toolkit中的pt-query-digest,可以把日志按执行次数、总耗时、平均耗时做聚合,立刻排出高频SQL榜单。配合mysqldumpslow也能做基础统计。定位到模板后,再结合执行计划与索引情况针对性调优,才能把数据库负载真正降下来。

开启慢查询日志只是SQL性能治理的第一步,真正麻烦的是从成千上万条记录里找出那些反复出现、拖慢整体吞吐的高频语句。如果靠肉眼翻文件,不仅效率极低,还会因为参数不同把同一条模板SQL误判成多条。我们需要用聚合分析思路把日志变成可排序的指标。

SQL慢查询日志开启后如何快速定位高频SQL

一、慢查询日志的基础配置回顾

在MySQL中,慢查询日志由几个系统变量控制。最关键是slow_query_log开关、long_query_time阈值以及slow_query_log_file路径。只有先保证日志在正常写入,后续分析才有原材料。很多同学开了开关却忘了调阈值,结果日志为空或者体量过大。

下面是一段典型的环境变量设置,注意long_query_time设为0.5秒,意味着超过半秒的语句都会落盘。生产环境若设为0会记录全部SQL,一般不推荐。配置后可用SHOW VARIABLES LIKE 'slow%'确认生效情况。

-- 开启慢查询日志并设置阈值
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 0.5;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';

-- 确认配置
SHOW VARIABLES LIKE 'slow_query_log';
SHOW VARIABLES LIKE 'long_query_time';

二、为什么不能直接读日志文本

慢日志原始内容长这样:每条含时间戳、用户、SQL文本、执行时长、锁时间、扫描行数。同一业务模板可能因为入参不同而出现几百次,人工无法汇总。更严重的是,有些框架会把SQL换行写,肉眼切分语句边界很容易出错。

另一个误区是只盯着“单条最慢”的SQL。偶尔一次跑十秒的报表查询,对系统压力远小于每秒执行两百次、每次八十毫秒的下单接口。高频且总量大的语句才是优化性价比最高的目标,这就必须用工具做分组计数。

# 原始慢日志片段示例(已转义尖括号)
# Time: 2023-09-01T10:00:01.123456Z
# User@Host: app[app] @  [192.168.0.1]
# Query_time: 0.082  Lock_time: 0.001 Rows_sent: 1  Rows_examined: 5000
SELECT * FROM order_tbl WHERE user_id=123 AND status=1;

三、使用 pt-query-digest 快速聚合

Percona Toolkit里的pt-query-digest是定位高频SQL的首选。它会解析日志,把指纹相同的SQL归并,输出按总耗时或执行次数排序的报告。报告里清楚列出某类语句的执行次数、占比、平均与最大耗时,一眼就能看到热点。

安装后执行一条命令即可。下面示例中--limit控制输出前十条,--order-by可按需要切换为cnt(次数)或query_time(耗时)。生成的报告头部还有整体统计,比如日志总语句数、唯一指纹数,帮助判断集中度。

# 安装工具(以Ubuntu为例)
apt-get install percona-toolkit

# 分析慢日志并按执行次数排前10
pt-query-digest --limit 10 --order-by cnt /var/log/mysql/slow.log > report.txt

# 查看报告摘要
head -n 40 report.txt

报告里每个指纹块都有# Rank# Count# Exec time等信息。比如看到某SELECT指纹Count占全量60%,平均执行0.05秒,但每秒上百次,那它就是典型高频SQL。接下来优先给它加复合索引或改写法,收益最明显。

四、轻量方案:mysqldumpslow

如果服务器不能装第三方工具,MySQL自带的mysqldumpslow也能做基础聚合。它按SQL模板分组,支持按次数-c、按平均时间-a等排序。虽然不如pt-query-digest细致,但胜在零依赖。

下面命令取出执行次数最多的前五个模板。注意它把具体参数替换为N,便于归并。缺点是无法给出响应时间分布曲线,也难以过滤特定库表,适合做初步筛查。

# 按执行次数排前5
mysqldumpslow -s c -t 5 /var/log/mysql/slow.log

# 按平均查询时间排前5
mysqldumpslow -s at -t 5 /var/log/mysql/slow.log

五、定位后的优化落地步骤

拿到高频SQL清单后,先拿原SQL进数据库跑EXPLAIN,看是否走索引、是否出现Using filesortUsing temporary。很多时候高频慢是因为缺失联合索引,或者查询条件对字段用了函数导致索引失效。

确认问题后,建索引或改写SQL,再回流到测试环境用相同日志模板压测。若Rows_examined明显下降、执行时间进入毫秒级,说明优化有效。最后把阈值调回业务可接受范围,避免日志无限膨胀。

-- 查看高频SQL的执行计划
EXPLAIN
SELECT * FROM order_tbl WHERE user_id=123 AND status=1;

-- 补充联合索引示例
ALTER TABLE order_tbl ADD INDEX idx_user_status (user_id, status);
工具安装成本聚合维度适用场景
pt-query-digest需装Percona Toolkit次数、耗时、锁、行数等深度分析与报告
mysqldumpslow数据库自带次数、平均时间快速初筛

六、常见坑与建议

有人把long_query_time设得太大,导致真正的高频轻量慢SQL不进日志,误以为系统很健康。建议初期设小一点,比如0.1到0.5秒,观察几天再调。另外日志文件要配轮转,否则磁盘写满会引发故障。

还有一点,定位高频SQL不是终点。若某语句来自烂代码里的循环查询,加索引只是缓解,根本做法是改成分批或join。分析时结合应用日志看调用链,才能从架构上消除瓶颈。

slow_query_logSQL优化pt_query_digest修改时间:2026-08-05 18:18:42

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