导读:本期聚焦于小伙伴创作的《MySQL慢查询日志怎么分析?慢查询定位与优化的实战方法有哪些?》,敬请观看详情。一条本该毫秒级返回的SQL突然拖垮了整个接口,这种性能劣化往往藏在慢查询日志里。MySQL的慢日志会记录执行时间超过long_query_time且扫描行数达标的语句,但原始日志可读性极差。直接翻文件效率低,应当先用mysqldumpslow按耗时、锁时间或扫描行数聚合,快速圈出高频问题SQL。定位后借助EXPLAIN观察访问类型与索引命中情况,重点看type、key和rows字段。若出现ALL全表扫描或临时表排序,通常意味着缺失索引或写法不当。优化时优先建立联合索引并调整WHERE与ORDER BY顺序,避免对字段套函数导致索引失效,必要时拆分大事务与深分页查询。

在数据库运维和开发工作中,慢查询是影响系统响应速度最常见的隐患之一。MySQL提供的慢查询日志功能,能够把执行时间超出阈值的SQL语句记录下来,为后续性能排查留下线索。不过,很多人拿到日志后不知道从哪下手,其实只要掌握正确的分析路径和优化思路,就能把原本拖慢系统的查询逐步理顺。

MySQL慢查询日志怎么分析?慢查询定位与优化的实战方法有哪些?

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

MySQL的慢日志并不是默认全面开启的,在生产环境我们需要通过参数来控制它的行为。核心参数包括slow_query_log、long_query_time以及min_examined_row_limit。slow_query_log设为1表示开启;long_query_time定义超过多少秒算慢查询,通常设为0.1到1之间;min_examined_row_limit则要求扫描行数大于该值才记录,避免记录那些虽慢但只查一行的无意义语句。

除了上述参数,还可以通过log_queries_not_using_indexes把未使用索引的查询也写进慢日志,这对发现潜在全表扫描非常有用。修改配置可以用SET GLOBAL方式临时生效,也可以写进配置文件永久保存。下面的示例展示了如何在线开启并设定阈值为0.2秒:

-- 临时开启慢查询日志
SET GLOBAL slow_query_log = 1;
-- 设置慢查询阈值为0.2秒
SET GLOBAL long_query_time = 0.2;
-- 记录未使用索引的查询
SET GLOBAL log_queries_not_using_indexes = 1;
-- 查看当前配置
SHOW VARIABLES LIKE 'slow_query_log';
SHOW VARIABLES LIKE 'long_query_time';

需要注意的是,long_query_time的修改在会话级可能不会立即影响当前连接,新开的会话才会使用新值。因此在验证配置时,建议重新连接后再执行测试SQL。另外,慢日志文件会不断增长,应配合logrotate或定时清理脚本,防止磁盘被撑满。

二、使用工具聚合分析慢日志

原始慢日志是纯文本,单条记录包含时间、用户、SQL以及执行信息,直接阅读效率很低。MySQL自带的mysqldumpslow工具可以按照不同维度排序并归并相似的SQL。比如按平均查询时间、总耗时或扫描行数来输出摘要,帮助我们快速锁定最该优先处理的问题。

常见用法中,-s t表示按总耗时排序,-s at按平均时间排序,-s c按出现次数排序。加上-t 10可以只显示前十条。以下命令按平均耗时取前十条慢SQL:

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

# 按总锁定时间排序
mysqldumpslow -s l -t 10 /var/lib/mysql/slow.log

# 按出现次数排序,并简化数字和字符串为N和S
mysqldumpslow -s c -t 20 -a /var/lib/mysql/slow.log

如果团队使用了Percona Toolkit,pt-query-digest能给出更丰富的报告,包括每个查询的响应时间分布、索引建议等。但对于大多数场景,mysqldumpslow已经足够找出主要矛盾。分析时不要只盯住单条最慢的,还要看那些频繁出现、单次不算极慢但累加开销巨大的查询。

三、借助EXPLAIN定位执行瓶颈

找到可疑SQL后,下一步是在前面加EXPLAIN来查看执行计划。EXPLAIN会告诉我们MySQL打算怎么访问表、用没用索引、大概扫描多少行。关键列有type、key、rows和Extra。type显示连接类型,从system、const到ALL,ALL代表全表扫描,通常是性能毒药;key显示实际选用的索引;rows是估算的扫描行数;Extra里若出现Using filesort或Using temporary,说明排序或分组没用到索引,需要警惕。

举一个常见反面例子:在WHERE条件里对索引列使用函数,会导致索引失效。如下面语句对create_time套了DATE函数,即使该列有索引也用不上:

-- 错误写法:索引列使用函数,导致全表扫描
EXPLAIN
SELECT * FROM orders
WHERE DATE(create_time) = '2023-05-01';

-- 正确写法:范围查询保留索引可用
EXPLAIN
SELECT * FROM orders
WHERE create_time >= '2023-05-01 00:00:00'
  AND create_time < '2023-05-02 00:00:00';

通过对比两个执行计划的type和key字段,可以直观看到第一个是ALL,第二个能用上range扫描。除了函数包裹,隐式类型转换(如字符串列传数字)也会让索引失效。因此写SQL时尽量保持字段原样参与比较,把计算放在常量侧。

四、索引与SQL写法的优化实践

定位到全表扫描或低效索引后,优先考虑建立合适的联合索引。联合索引遵循最左前缀原则,把区分度高的列放在前面,并把常用于等值过滤的列置于范围列之前。例如用户订单表常按user_id和状态查询,再按时间排序,就可以建(user_id, status, create_time)的索引。

同时,深分页也是一个典型慢查询来源。LIMIT 100000, 20这种写法要扫描并丢弃前十万行。优化办法是利用上一页最大ID做游标分页,如下面示例所示:

-- 常规深分页,性能差
SELECT * FROM orders
ORDER BY id DESC
LIMIT 100000, 20;

-- 游标分页,利用索引定位起点
SELECT * FROM orders
WHERE id < 上一页最小ID
ORDER BY id DESC
LIMIT 20;

此外,只返回需要的列、避免SELECT *,能减少回表和数据传输。对于统计类大查询,可以放到从库执行,或使用汇总表定时计算。写多读少的场景,还可考虑冗余字段来换查询效率。优化不是一次性的,应把慢日志分析纳入日常巡检,才能持续保持数据库健康。

五、总结与落地建议

慢查询分析是一条从配置、采集、聚合到定位、优化的完整链路。先把慢日志参数设合理,再用mysqldumpslow等工具找出重点SQL,接着用EXPLAIN看清执行计划,最后通过建索引、改写法、调结构来消除瓶颈。整个过程不需要高深工具,关键是养成周期性复盘的习惯。

建议大家在测试环境故意造一些慢SQL,走一遍上述流程,熟悉各命令输出含义。等到生产真出问题,就能从容取出慢日志、快速定位并给出修改方案,把对业务的影响降到最低。

MySQL慢查询日志索引优化修改时间:2026-08-02 22:48:33

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