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

MySQL慢SQL瓶颈定位

一、整体分析思路

遵循「耗时拆分 → 执行计划定位 → 资源/锁/IO排查 → 语句逻辑分析」四步,先分清是扫描多、排序/分组、锁等待、IO高、网络/返回数据量大哪一类瓶颈。

二、第一步:拆分SQL总耗时(区分时间去向)

一条SQL总耗时 =执行耗时 + 锁等待耗时 + IO耗时 + 网络传输耗时
先通过日志/状态判断时间花在哪。

1. 从慢查询日志提取核心指标

慢日志单条记录关键字段:

  • Query_time总执行时间(核心)
  • Lock_time:等待表/行锁的时间
  • Rows_sent:返回给客户端的行数
  • Rows_examined:MySQL实际扫描的行数
  • Rows_read:读取数据行数

快速判断瓶颈类型

  1. Lock_time 占比高→ 瓶颈:锁竞争(并发高、事务长、行锁升级为表锁)
  2. Rows_examined 远大于 Rows_sent→ 瓶颈:无效扫描(索引失效/无索引)
  3. Query_time 高、行数不多、出现 filesort/temporary→ 瓶颈:排序/临时表
  4. Rows_sent 极大→ 瓶颈:返回数据过多、网络传输慢
  5. 磁盘IO飙升、CPU高 → 瓶颈:全表扫描/大量随机IO

三、第二步:EXPLAIN 深度分析执行计划(核心瓶颈定位)

EXPLAIN是定位SQL内部瓶颈的核心,按字段逐一判断问题点,按优先级从高到低排查。

1. 访问类型 type(最关键,代表数据读取方式)

优先级:system > const > eq_ref > ref > range > index > ALL

type 值瓶颈说明严重程度
ALL全表扫描,逐行遍历整张表,CPU+IO双重消耗严重,必须优化
index全索引扫描,比全表扫描略好,但依然遍历整个索引树高,需优化
range范围查询(> < between in like 前缀匹配),范围过大则性能差中等,看扫描范围
ref/eq_ref正常索引命中,无明显瓶颈正常

典型场景type=ALL基本可以确定是缺失索引或索引失效

2. key / possible_keys(索引使用情况)

  • possible_keys:理论可用索引
  • key=NULL未使用任何索引,主瓶颈就是索引问题
  • key有值但type=ALL:索引存在但被SQL逻辑规避,索引失效

3. rows(预估扫描行数)

MySQL预估需要扫描的行数,数值越大,IO/CPU开销越高

  • 单表查询:几十万+行扫描 = 严重瓶颈
  • 多表JOIN:驱动表rows大,会导致后续表循环匹配次数暴增

4. Extra 额外信息(隐藏瓶颈重灾区)

这是排序、分组、临时表、回表等隐性瓶颈的主要来源:

  1. Using filesort

    • 含义:无法利用索引排序,MySQL在内存/磁盘做文件排序
    • 瓶颈:排序消耗CPU+临时IO,数据量越大越慢
    • 触发:ORDER BY字段无索引、排序字段不在联合索引末尾、多字段排序顺序不一致
  2. Using temporary

    • 含义:MySQL创建临时表存放中间结果
    • 瓶颈:临时表涉及内存/磁盘读写,并发下性能暴跌
    • 触发:GROUP BYDISTINCTUNION、子查询、多表聚合无索引
  3. Using index

    • 含义:覆盖索引,无需回表查询数据,性能最优,无瓶颈
  4. Using where

    • 正常:索引过滤后再行条件判断;
    • 异常:配合type=ALL代表全表扫描后逐行过滤,开销极大。
  5. Using join buffer (Block Nested Loop)

    • 含义:JOIN 关联字段无索引,使用连接缓冲区做嵌套循环
    • 瓶颈:多表关联严重低效,属于JOIN索引缺失问题。

5. id & select_type(子查询/关联查询瓶颈)

针对多表、子查询、UNION语句:

  • DERIVED:派生表(子查询生成临时表),高频出现则是瓶颈
  • SUBQUERY:无法优化的子查询,执行多次,叠加耗时
  • 多表id混乱、执行顺序不合理:JOIN 驱动表选择错误(大表驱动小表)

四、第三步:区分四大类典型性能瓶颈+根因分析

结合日志 + Explain,把问题归为4大类,精准定位根因。

类别1:索引类瓶颈(最高发)

现象

  • Explain:type=ALL/indexkey=NULL
  • 慢日志:Rows_examined极大,Lock_time正常

根因

  1. Where/Order by/Group by 字段未建索引
  2. 索引失效:隐式类型转换、索引列运算/函数、like %xxxor跨索引、is not null/not in
  3. 索引区分度太低(低基数索引,如性别、状态),MySQL放弃使用
  4. 联合索引顺序不合理(未遵循最左匹配)

类别2:排序/分组瓶颈(filesort + temporary)

现象

  • Explain:Using filesort/Using temporary
  • 慢日志:扫描行数不多,但 Query_time 偏高

根因

  1. ORDER BY/GROUP BY字段未纳入联合索引
  2. 聚合、去重操作(DISTINCT、UNION)数据量过大
  3. 内存排序空间不足,排序落地到磁盘文件

类别3:锁/事务瓶颈(并发场景高发)

现象

  • 慢日志:Lock_time占总耗时 30% 以上
  • 实时show processlist:大量会话处于Locked状态

根因

  1. 事务执行时间过长,行锁迟迟不释放
  2. 批量更新/删除无索引,行锁升级为表锁
  3. 并发争抢同一行数据,锁等待队列堆积
  4. 死锁(会话互相等待)

类别4:数据量/IO/网络瓶颈

现象1:大结果集返回

  • 慢日志:Rows_sent成千上万行
  • 现象:查询本身很快,但客户端接收数据慢
  • 根因:SELECT *、未分页、一次性返回全量数据,网络传输+客户端解析耗时高

现象2:大分页瓶颈

  • 语句:LIMIT 100000, 10
  • 根因:MySQL需要先扫描前10万行再丢弃,偏移量越大扫描行数越多

现象3:磁盘IO瓶颈

  • 服务器监控:磁盘读IO 100%、CPU 偏高
  • 根因:频繁全表扫描、无覆盖索引导致大量回表查询、临时表/排序落地磁盘

五、第四步:实时状态辅助分析(线上运行中SQL)

适合排查正在执行的慢SQL,补充静态日志的不足。

1. show full processlist

  • 状态Copying to tmp table:正在创建临时表 → 临时表瓶颈
  • 状态Sorting result:正在排序 → filesort 瓶颈
  • 状态Locked:被锁阻塞 → 锁瓶颈
  • 状态Sending data:正在传输结果集 → 网络/返回数据量大

2. 系统状态变量(全局负载)

-- 查看全表扫描次数showglobalstatuslike'Handler_read%';-- 临时表统计(磁盘临时表多=严重瓶颈)showglobalstatuslike'Created_tmp%';-- 文件排序次数showglobalstatuslike'Sort%';
  • Created_tmp_disk_tables持续上涨:大量临时表落地磁盘
  • Sort_merge_passes高:排序内存不足,多次合并排序文件

六、快速分析流程(实战速用)

  1. 看慢日志:对比Lock_time/Rows_examined/Rows_sent,初步划分瓶颈大类
  2. 执行EXPLAIN:优先看typekeyExtra,确认索引、排序、临时表问题
  3. 结合processlist+ 服务器监控:判断是否锁、IO、CPU 资源瓶颈
  4. 回看SQL语法:检查是否分页不当、SELECT *、索引失效写法、不合理子查询/JOIN

七、补充:常见误区

  1. 只看执行时间,不看扫描行数:有些SQL耗时1秒,但扫描百万行,并发后直接雪崩
  2. 有索引就万事大吉:索引失效、联合索引顺序错误依然会慢
  3. 忽略锁等待:并发场景下,锁等待比SQL本身执行更耗时
  4. 轻视临时表/文件排序:数据量上涨后,这两类问题会指数级变慢
http://www.jsqmd.com/news/996147/

相关文章:

  • STM8L152C6T6低功耗开发板资料包:原理图+中文手册+V1.5.1固件库+实测低功耗例程(含0.38μA记录)
  • 计算机毕业设计之django协同过滤算法的音乐推荐研究
  • 别再死记公式了!用PyTorch的BatchNorm1d/2d跑个Demo,5分钟搞懂它到底在算啥
  • 从RTP包到多协议流:拆解ZLMediaKit中MultiMediaSourceMuxer的‘万能转换’核心
  • Retrieval-based-Voice-Conversion-WebUI:如何用10分钟语音数据训练高质量AI变声模型
  • QT5.13写的双端TCP聊天工具:服务端+多客户端,带完整可执行文件和源码
  • AUTOSAR MPU不只是隔离:在Cortex-M芯片上实现‘最小权限’设计的三个实战技巧
  • 充电桩共享场景下的动态定价策略与收益优化
  • 2026年达州高考志愿填报机构怎么选?深度盘点四川本土靠谱机构与避坑指南 - 优质品牌商家
  • 冻雪清扫车结构设计(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_可以扫码或者私信
  • 别再死记硬背AXI信号了!用FPGA实战案例带你理解AXI4、AXI-Lite和AXI-Stream的区别
  • 期末复习总结
  • Windows 11优化终极指南:如何用Win11Debloat免费工具让你的电脑运行如飞
  • 浙江好用的中铁标准抑尘剂生产厂家推荐2026 - 品牌排行榜
  • GEE实战:像元二分法反演区域植被覆盖度(FVC)的技术流程与调优
  • 当GAN变成‘黑客’:AdvGAN如何轻松骗过自动驾驶CNN?一个给安全工程师的视觉化解读
  • MPC8560高速接口设计实战:DDR与以太网时序规范与PCB实现
  • 2026年更新:泰州有实力的死刑辩护律师咨询与专业服务商解析 - 品牌鉴赏官2026
  • 2026年宁国装饰市场深度分析:本土服务商综合实力与口碑观察 - 优质品牌商家
  • STM32F407读取AD7616(CM2249)
  • CODESYS SoftMotion 3.5.19.40 实战:不用电子凸轮,如何让Delta机械手跟上传送带和转盘?
  • 从配置到跑通:手把手调试FiRa MAC动态STS密钥派生(KDF/CCM*实战)
  • 2026年管理咨询公司可靠性深度分析:行业现状、核心维度与代表性机构盘点 - 优质品牌商家
  • 从一次‘难看’的上电波形说起:手把手教你用稳压电源和示波器优化电源时序
  • 如何为洛雪音乐解锁全网音源:音乐自由探索的完整指南
  • 深度解析Roboto字体:全面掌握多语言排版与Unicode支持的实用指南
  • AUTOSAR内存保护:除了MPU,你还需要了解这些容易被忽略的配置陷阱
  • MAX30102心率血氧算法核心代码逐行解读:从FIFO数据到心率血氧值的计算过程
  • 从PSG到FSG:聊聊芯片里那些“玻璃”层是怎么用CVD“吹”出来的
  • 给Linux驱动开发者的PCI配置空间Header实战指南:手把手教你读懂BAR、中断与命令寄存器