游乐游手机版
首页/数据库/文章详情

MySQL生产环境定位全表扫描慢事务的排查方法

时间:2026-07-19 09:12
通过EXPLAIN的type字段为ALL、key为NULL、rows接近总行数等信号可判断全表扫描。使用SHOWPROCESSLIST或INFORMATION_SCHEMA PROCESSLIST快速定位慢查询。索引失效常见于函数调用、隐式类型转换、左模糊查询及联合索引顺序错误。建议优先覆盖WHERE条件加索引,并用pt-online-schema-chan
判断一条SQL语句是否正在执行全表扫描,最直接的方法就是查看`EXPLAIN`输出中的`type`字段。如果该字段显示为`ALL`,那就意味着确实没有使用索引——不是“可能”,而是确凿无疑。除此之外,还有几个关键信号值得重点关注:`key`字段为`NULL`、`rows`数量接近总行数、`Extra`里出现`Using where`但没有`Using index`。这些信号组合在一起,基本可以断定MySQL正在被迫执行全表扫描,性能堪忧。 如何在生产环境定位MySQL中那些导致全表扫描的慢事务? ## 怎么快速揪出正在全表扫描的 SQL? 不必等到慢查询日志积累大量数据后再去分析。直接连接生产数据库,执行`SHOW PROCESSLIST`命令,查看当前活跃会话中哪些正在扫描大表: - `State`是`Sending data`且`Time`超过几秒,大概率是在扫描; - `Info`字段里包含`SELECT` + 大量`WHERE`条件但缺少`ORDER BY`或`LIMIT`,尤其要留意有没有函数调用(比如`DATE(created_at)`这种); - 配合`INFORMATION_SCHEMA.PROCESSLIST`查询更全面:`SELECT ID, INFO, TIME FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND = 'Query' AND TIME > 3 AND INFO LIKE '%SELECT%';` ## EXPLAIN 里哪些信号说明它在全表扫描? `EXPLAIN`不是走马观花,重点盯住三个字段: - `type`是`ALL`:确凿证据,没有使用任何索引; - `key`是`NULL`:即使`possible_keys`有值,`key`为空也等于索引未被采用; - `rows`数字极大(比如超过50000):哪怕`type`是`index`,扫描整棵索引树也等价于全表扫描; - `Extra`出现`Using where`但没`Using index`:说明查询使用了索引还需要回表,如果`rows`很大,实际开销接近全表扫描。 ## 为什么明明建了索引还全表扫描?常见失效场景 索引存在 ≠ 被使用。以下几种写法会让MySQL直接放弃索引: - WHERE中对字段使用了函数:`WHERE YEAR(create_time) = 2026` → 改为`WHERE create_time >= '2026-01-01' AND create_time < '2027-01-01'`; - 隐式类型转换:`WHERE user_id = '123'`(`user_id`是INT类型)→ 字符串强制转为数字,索引失效; - LIKE左模糊:`WHERE name LIKE '%abc'` → 无法走B+树前缀匹配; - 联合索引顺序错误:`INDEX(a,b,c)`,但查询只用`WHERE c = 1` → 不满足最左前缀原则,直接跳过。 ## 线上不敢随便改 SQL?先加索引试试 如果确认是缺失索引导致的`ALL`,添加索引比重写业务逻辑快得多,但需要注意: - 优先覆盖`WHERE`条件字段,再追加`ORDER BY`和`SELECT`字段(做成覆盖索引); - 避免单列索引堆砌,比如`WHERE a=1 AND b=2`,建`INDEX(a,b)`比分别建两个单列索引更好; - 加索引前使用`pt-online-schema-change`或MySQL 8.0+的`ALGORITHM=INSTANT`,避免锁表; - 加完索引后立即用`EXPLAIN`验证,不要相信“应该能走”。 全表扫描本身并不致命,致命的是它出现在高频接口或大表上。真正麻烦的是那些`rows`显示几千、但实际执行扫了百万行的SQL——`EXPLAIN`的预估不准时,需要借助`SHOW PROFILE`或性能模式(`performance_schema`)查看真实I/O开销。
来源:https://www.php.cn/faq/2812551.html
上一篇MongoDB分片集群应对亿级数据处理挑战方案 下一篇Agent场景动态JSON性能详细对比拆解:Doris比ClickHouse快7倍,比ES快2倍
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
利用AWR报告诊断表空间碎片对扫描性能的影响
数据库 · 2026-07-19

利用AWR报告诊断表空间碎片对扫描性能的影响

通过AWR报告中dbfilesequentialread等待异常、物理读请求次数增幅远超读块数、以及SQL执行计划从索引扫描退化为全表扫描这三类信号交叉验证,可判断表空间碎片是否拖慢扫描性能,避免误判。

MySQL第三方审计系统只读系统视图权限配置方法
数据库 · 2026-07-19

MySQL第三方审计系统只读系统视图权限配置方法

为审计账号配置MySQL只读权限时,performance_schema必须逐表显式授权,不可使用* *或库级批量授权;认证插件必须指定mysql_native_password;无法通过视图封装,必须直接授权原始表。这是审计账号配置的关键注意事项,必须严格遵守,并遵循最小权限原则。

Navicat团队项目自定义图标背景色设置方法
数据库 · 2026-07-19

Navicat团队项目自定义图标背景色设置方法

Navicat中设置团队项目图标背景色实为两个独立配置:模型图节点颜色需手动修改navicat ini文件并完全重启;SQL编辑器及主窗口背景色通过主题设置。版本一致、配置路径准确、激活ERD模式是效果一致的关键。修改后必须彻底退出程序。

SQL嵌套查询中如何有效利用索引覆盖提升性能
数据库 · 2026-07-19

SQL嵌套查询中如何有效利用索引覆盖提升性能

SQL嵌套查询中,子查询字段未被索引覆盖会导致全表扫描,而外层EXPLAIN的Usingindex可能误导优化。需为子查询过滤字段建索引,联合索引将SELECT字段包含在内且顺序正确。PostgreSQL可用INCLUDE或组合索引,MySQL8 0+支持函数索引,物化视图需手动建索引并刷新统计信息。

SQL窗口函数快速查找用户多设备登录顺序
数据库 · 2026-07-19

SQL窗口函数快速查找用户多设备登录顺序

使用ROW_NUMBER()配合PARTITIONBYuser_id和ORDERBYlogin_time,可快速按用户分组并排序登录顺序。漏掉PARTITIONBY会导致全局编号,且必须用ROW_NUMBER()保证编号连续,避免RANK()或DENSE_RANK()的跳号问题。区分首次登录可嵌套MIN()窗口函数。老版本MySQL用变量模拟易出错,建议升级