当前位置: 首页 > news >正文

MySQL慢查询日志:找到那些偷偷变慢的SQL

MySQL慢查询日志:找到那些偷偷变慢的SQL

目录

  • 慢查询日志是什么
  • 开启慢查询日志
  • 慢查询日志长什么样
  • mysqldumpslow:日志分析工具
  • 配合 EXPLAIN 做深度分析
  • 常见问题排查清单
  • 小结

慢查询日志是什么

慢查询日志是 MySQL 提供的一个功能,它会把执行时间超过指定阈值的 SQL 语句记录到文件里。

有了慢查询日志,你就不用一行一行翻代码去猜哪条 SQL查询较慢可能存在问题,直接看日志就可以找到问题SQL。

MySQL 默认是关闭慢查询日志的,因为记录日志本身有性能开销,所以生产环境通常只在排查问题时临时开启,或者设置一个相对严格的阈值(比如 1 秒),只记录真正有问题的 SQL。

开启慢查询日志

查看当前状态

-- 查看慢查询日志是否开启SHOWVARIABLESLIKE'slow_query_log';-- 查看阈值(单位:秒)SHOWVARIABLESLIKE'long_query_time';-- 查看日志文件路径SHOWVARIABLESLIKE'slow_query_log_file';

正常情况下,slow_query_log的值是OFFlong_query_time默认是 10 秒。10 秒太宽松了,生产环境一般设成 1 秒甚至 0.5 秒,主要还是取决于业务场景。

临时开启(当前会话生效)

-- 开启慢查询日志SETGLOBALslow_query_log='ON';-- 设置阈值为 1 秒(超过 1 秒的 SQL 才记录)SETGLOBALlong_query_time=1;-- 可选:记录没有使用索引的 SQLSETGLOBALlog_queries_not_using_indexes='ON';

SET GLOBAL设置的参数在 MySQL 重启后会失效,下次启动还是用配置文件里的值。

永久开启(修改配置文件)

编辑 MySQL 的配置文件my.cnf(Linux)或my.ini(Windows),在[mysqld]段落下添加:

[mysqld] # 开启慢查询日志 slow_query_log = 1 # 慢查询阈值:1 秒 long_query_time = 1 # 日志文件路径(可以自定义) slow_query_log_file = /var/log/mysql/slow.log # 可选:记录没有使用索引的 SQL log_queries_not_using_indexes = 1

修改之后重启 MySQL,或者执行SET GLOBAL命令让配置立即生效。

一个小技巧log_queries_not_using_indexes这个参数很实用。它会把所有没走索引的 SQL 都记录下来,不管执行时间多长。这类 SQL 在数据量小的时候可能跑得很快,但随着数据增长会越来越慢,属于"定时炸弹",有了这个功能就可以早点发现早点处理。

慢查询日志长什么样

开启之后,我们来制造一条慢查询,看看日志长什么样。

先准备一张测试表和一些数据:

CREATETABLEuser_order(idBIGINTPRIMARYKEYAUTO_INCREMENT,user_idBIGINTNOTNULL,order_noVARCHAR(32)NOTNULL,amountDECIMAL(10,2),statusVARCHAR(20),create_timeDATETIME,INDEXidx_user_id(user_id))ENGINE=InnoDB;-- 插入 100 万条测试数据DELIMITER//CREATEPROCEDUREgenerate_orders(INnINT)BEGINDECLAREiINTDEFAULT0;WHILEi<nDOINSERTINTOuser_order(user_id,order_no,amount,status,create_time)VALUES(FLOOR(RAND()*10000),CONCAT('ORD',LPAD(i,10,'0')),ROUND(RAND()*1000,2),ELT(FLOOR(RAND()*3)+1,'pending','paid','cancelled'),DATE_SUB(NOW(),INTERVALFLOOR(RAND()*365)DAY));SETi=i+1;ENDWHILE;END//DELIMITER;CALLgenerate_orders(1000000);

现在执行一条故意不走索引的查询:

-- 对 status 做模糊查询,status 上没有索引SELECT*FROMuser_orderWHEREstatusLIKE'p%'ORDERBYcreate_timeDESCLIMIT50;

等它跑完(可能要几秒),然后去日志文件里找找看。日志文件的路径可以用SHOW VARIABLES LIKE 'slow_query_log_file'查看。

一条典型的慢查询日志长这样:

# Time: 2026-06-21T14:32:05.123456+08:00 # User@Host: root[root] @ localhost [] Id: 42 # Query_time: 2.356789 Lock_time: 0.000123 Rows_sent: 50 Rows_examined: 1000000 SET timestamp=1718946725; SELECT * FROM user_order WHERE status LIKE 'p%' ORDER BY create_time DESC LIMIT 50;

逐行解读:

字段含义重点关注
TimeSQL 执行的时间点定位问题发生的时刻
User@Host执行 SQL 的用户和来源排查是不是某个服务在搞事
Query_timeSQL 执行总耗时(秒)核心指标,越小越好
Lock_time等待锁的时间(秒)如果很大,说明有锁竞争
Rows_sent返回给客户端的行数和 LIMIT 对比,看有没有多返回
Rows_examined扫描的行数核心指标,越大说明越低效
SQL 语句实际执行的 SQL拿去 EXPLAIN 分析

最该关注的两个数字:Query_time 和 Rows_examined。

Query_time 告诉你这条 SQL 到底慢不慢,Rows_examined 告诉你它为什么慢。如果 Rows_examined 是 100 万,但 Rows_sent 只有 50,说明 MySQL 扫了 100 万行才挑出 50 条——这就是典型的索引缺失或索引失效。

mysqldumpslow:日志分析工具

日志文件看几条还行,但如果慢查询很多,一条条翻就太低效了。MySQL 自带了一个日志分析工具mysqldumpslow,可以帮我们做汇总统计。

# 按执行时间排序,取前 10 条最慢的mysqldumpslow-st-t10/var/log/mysql/slow.log# 按扫描行数排序,取前 10 条mysqldumpslow-sr-t10/var/log/mysql/slow.log# 按执行次数排序,取前 10 条mysqldumpslow-sc-t10/var/log/mysql/slow.log

参数说明:

参数含义
-s t按总执行时间排序(默认)
-s r按扫描总行数排序
-s c按执行次数排序
-s l按锁等待时间排序
-t N只显示前 N 条
-g "pattern"只匹配包含指定字符串的 SQL

输出结果类似:

Count: 125 Time=2.36s (295s) Lock=0.00s (0.15s) Rows=50.0 (6250), root[root]@localhost SELECT * FROM user_order WHERE status LIKE 'S' ORDER BY create_time DESC LIMIT N

这一行告诉我们:这条 SQL 在统计时段内执行了 125 次,平均耗时 2.36 秒,累计耗时 295 秒,平均扫描行数 6250 条。

Count 大的说明是高频 SQL,Time 大的说明是耗时大户。如果一条 SQL Count 和 Time 都大,那它就是性能优化的第一优先级。

配合 EXPLAIN 做深度分析

慢查询日志帮你找到了"嫌疑人",但要定罪还需要充分的证据。所以在拿到日志里的 SQL 后,我们继续用EXPLAIN看看它的执行计划:

EXPLAINSELECT*FROMuser_orderWHEREstatusLIKE'p%'ORDERBYcreate_timeDESCLIMIT50;

输出可能是:

+----+------+-------+------+---------+------+----------+-----------------------------+ | id | type | key | ref | rows | filtered | Extra | +----+------+-------+------+---------+----------+------------------------------------+ | 1 | ALL | NULL | NULL | 1000000 | 33.33 | Using where; Using filesort | +----+------+-------+------+---------+----------+------------------------------------+

四个危险信号:

  1. type = ALL:全表扫描,没走索引
  2. key = NULL:没有可用索引
  3. rows = 1000000:扫描了 100 万行
  4. Extra = Using filesort:额外排序

和日志里的 Rows_examined = 1000000 对上了。问题很明确:status列没有索引,MySQL 只能全表扫描。

优化方案:给status加索引,或者改成联合索引(status, create_time)同时覆盖过滤和排序:

ALTERTABLEuser_orderADDINDEXidx_status_time(status,create_time);

再查一次 EXPLAIN:

+----+-------+----------------+------+---------+------+----------+-------+ | id | type | key | ref | rows | filtered | Extra | +----+-------+----------------+------+---------+----------+-------------+ | 1 | range | idx_status_time| NULL | 333333 | 100.00 | Using where | +----+-------+----------------+------+---------+----------+-------------+

type 从 ALL 变成了 range,rows 从 100 万降到了 33 万,Using filesort 也没了。执行时间从 2 秒多降到几百毫秒。

慢查询日志负责"发现问题",EXPLAIN 负责"定位原因",两者配合才是完整的调优链路。

常见问题排查清单

拿到慢查询日志后,按照这个清单逐项检查:

现象可能原因排查方法
Rows_examined 远大于 Rows_sent索引缺失或索引失效EXPLAIN 看 type 和 key
Query_time 大但 Rows_examined 不大锁等待、IO 等待关注 Lock_time,检查是否有表锁
同一条 SQL 时快时慢执行计划不稳定EXPLAIN 看是否有多个候选索引
日志里出现大量相同 SQL慢查询集中在某几张表mysqldumpslow -s c 统计频次
某个时间段集中出现慢查询定时任务、批量导入检查 Time 字段的时间分布
Lock_time 很大有事务长时间未提交检查SHOW ENGINE INNODB STATUS

一个实用的排查流程:

小结

**慢查询日志是 MySQL 性能排查的起点。**它帮你从海量 SQL 中筛选出真正有问题的那些,附上执行时间、扫描行数等关键指标,让你的调优工作有的放矢。

从实际操作来看,慢查询日志 + EXPLAIN 是一对黄金搭档。前者负责"发现",后者负责"诊断"。发现问题是第一步,解决问题是第二步,在后端面试之中遇到“mysql如何调优”这个问题,我们就可以采用这个思路进行回答。在实际工作生产环境中,我们依然使用这个思路进行实际的排查优化。

http://www.gsyq.cn/news/1570145.html

相关文章:

  • 变革管理经典书籍推荐,这三本书做好组织变革必看
  • WiFi指纹定位自适应半径近邻搜索:从原理到工程实现
  • 3分钟完成漫画翻译:BallonTranslator深度学习辅助工具完全指南
  • 2026年现阶段斜板沉淀池生产厂家推荐哪家?江苏鑫邦达环保设备有限公司深度解析 - 品牌鉴赏官2026
  • Ubuntu 24.04 apt-key废弃后安全添加第三方仓库的正确方法
  • D2DX宽屏补丁:让经典暗黑破坏神2在现代PC上重获新生的终极解决方案
  • 大模型微调/RAG/Agent开发培训怎么选 2026年5家机构横向对比 - 互联网科技品牌测评
  • 2026年更新指南:聚焦成都知名的宴会桌椅优质厂家 - 品牌鉴赏官2026
  • 终极指南:如何免费使用跨平台iOS虚拟定位工具进行开发测试
  • Ubuntu 16.04 EOL环境下Icinga2监控系统部署实践
  • FramePack:轻松上手AI视频生成的完整指南
  • 2026年浙江老爹鞋生产厂商可靠度解析:聚焦供应链实力与市场新格局 - 品牌鉴赏官2026
  • SPARSEGEN:用稀疏查询破解3D生成视角偏差难题
  • 寄快递收费标准大揭秘,到底哪个最便宜划算? - 快递物流资讯
  • 大模型推理加速工程 2026:投机解码、KV Cache 与 PagedAttention 的深度优化实战
  • 强化学习之父Sutton联手毁灭战士之父Carmack:让机器人进入真实世界打游戏
  • Zotero-SciHub插件完整教程:一键解决学术文献下载难题
  • PCL2启动器:5分钟快速上手的Minecraft免费启动工具完整教程
  • 如何3步完成智能图层分离:LayerDivider让你的插画编辑效率提升500%
  • PN7150 NFC控制器低功耗模式实战:从原理到调优,实现百倍功耗优化
  • 2026年数字展厅全彩屏厂家怎么选?关键看这些维度 - 品牌排行榜
  • 线性化与等待自由:基于指纹的并发寄存器算法原理与实践
  • ICMP协议详解:网络故障排查的好帮手,ping命令的底层原理
  • 无限状态马尔可夫链计算:RG分解、截断与GTH算法实战解析
  • 讲真的2026年潍坊劳动律师推荐 这5位律师各有专长信得过 - 本地品牌推荐
  • 恒力机械五金集团统率 ERP、统率 WMS、统率 MES - 品牌发掘
  • Ubuntu 18.04 安装 Jekyll 的系统级兼容性问题与解决方案
  • 坐标系统详解
  • 多模态大模型在食品感官评估中的应用:从技术原理到工程实践
  • 2026湛江漏水检测维修本地口碑防水商家榜单:厨卫/阳台/屋面/地下室渗漏水维修,持证施工+明码实价,防水补漏公司TOP5推荐 - 即刻修防水