MySQL EXPLAIN 怎样分析 UPDATE 或 DELETE 的执行计划
来源:17golang原创
时间:2026-10-23 04:26:49 343浏览 收藏
MySQL 的 UPDATE 和 DELETE 并不需要“先执行再看结果”。在真正改数据前,可以先用 EXPLAIN 观察优化器准备怎样找到目标行:走哪个索引、预计扫描多少行、过滤条件放在哪里。最重要的边界是:这份计划是读取路径的估算,不是已经修改的行数,也不等于真实运行耗时。
官方地址:https://dev.mysql.com/doc/refman/8.4/en/explain.html
EXPLAIN UPDATE和EXPLAIN DELETE用来预估访问路径,不会直接执行对应的写入动作。- 先看
type、key、rows、filtered,再决定是否需要改索引或缩小范围。 - 计划中的
rows是估算值;生产 DML 仍要配合分批、备份、事务和回滚方案。
先把 UPDATE 和 DELETE 变成可读的计划
假设订单表按客户和创建时间筛选,先把要执行的语句原样放到 EXPLAIN 后面。下面的 SQL 只展示计划读取路径,关键是不要为了“看看效果”直接去掉 EXPLAIN。
-- 先查看 UPDATE 的读取路径,不会执行这次状态修改。
EXPLAIN
UPDATE orders
SET status = 'archived'
WHERE customer_id = 1001
AND created_at
MySQL 文档把 EXPLAIN 的适用对象扩展到 SELECT、UPDATE、DELETE、INSERT 和 REPLACE。因此,写入语句的第一道门可以统一成“先看读路径,再决定写范围”。

按四个字段判断计划是否值得执行
计划输出字段很多,排查 UPDATE 或 DELETE 时先抓住四个高价值字段。它们要放在一起看,不能只看到 type=ALL 就立即断定语句一定错误,也不能只看到 key 有值就认为风险已经消失。
| 字段 | 重点问题 | 常见判断 |
|---|---|---|
type | 怎样访问表 | const、eq_ref、ref 通常比 ALL 更容易控制范围;仍要结合数据分布。 |
possible_keys | 哪些索引可能有用 | 为空不一定代表语句错,但说明优化器没有发现可用索引。 |
key | 最终选了哪个索引 | 为空时重点检查条件、类型转换、函数包裹和索引顺序。 |
rows、filtered | 预计读多少、剩多少 | 两者结合估算读取压力;它们是统计信息推算,不是最终受影响行数。 |
例如 key 有值但 rows 仍很大,可能是索引选择性不足,或者复合索引的最左列不能有效缩小范围。反过来,rows 看起来很小,也不能跳过业务条件确认,因为统计信息可能已经过期。
全表扫描时先查条件和索引的对应关系
type=ALL 表示全表扫描。对小表或确实要处理大多数行的批量任务,它未必是问题;但对生产大表的 UPDATE、DELETE,它往往意味着锁持有时间、日志量和回滚成本会一起上升。
先检查三个方向:过滤列是否有索引;复合索引的列顺序是否让等值条件和范围条件落在可利用位置;条件两侧的数据类型是否一致。不要为了让计划出现索引就盲目新增索引,写入还会带来索引维护成本。
-- 用实际写入条件设计复合索引时,先把等值列放在前面。
CREATE INDEX idx_orders_customer_created
ON orders (customer_id, created_at);
-- 建索引后重新查看计划,确认读取范围是否真的缩小。
EXPLAIN
UPDATE orders
SET status = 'archived'
WHERE customer_id = 1001
AND created_at
如果条件对列使用函数、隐式转换,或者把范围写在无法利用索引的位置,新增索引也可能没有预期效果。先让计划解释“为什么读这些行”,再决定是否改 SQL。
复杂语句用 JSON 计划补充判断
表连接、派生表或多个条件组合在一起时,表格输出可能不够直观,可以改用 JSON 格式。它适合查看更完整的访问节点和成本信息,但仍然属于优化器估算,不能把 JSON 中的数字当作真实影响行数。
-- JSON 计划适合复杂 DML;仍然只做计划预估,不执行删除。
EXPLAIN FORMAT=JSON
DELETE FROM orders
WHERE customer_id = 1001
AND created_at
生产执行前,我会把计划和数据安全动作分开:先在测试或影子环境确认范围,正式任务再加上明确的主键边界,必要时按主键区间分批,并记录每批影响行数。对于不可逆的删除,备份或可恢复副本应先于 SQL 调优。

执行前的简短检查清单
- 语句先加
EXPLAIN,确认没有误删WHERE。 - 记录
type、key、rows、filtered,不要只看一个字段。 - 确认计划中的索引和条件与本次数据范围一致,注意统计信息和参数类型。
- 大表写入优先按主键或时间边界分批,并为失败批次保留恢复路径。
- 把计划估算与实际影响行数分开记录,避免把
rows当成最终结果。
常见问题
EXPLAIN UPDATE 会不会真的修改数据? 不会,它返回优化器对读取路径的计划;真正执行前仍要检查权限、锁和数据范围。
key 为空是不是一定要加索引? 不一定。小表、需要读取大多数行的任务或统计信息判断都可能让全表扫描合理,先结合数据规模和业务范围判断。
rows 能不能当成 DELETE 最终删除行数? 不能。它是估计要读取的行数,最终影响行数还取决于条件、并发变化和实际数据。
为什么有索引仍然扫描很多行? 常见原因是选择性低、复合索引顺序不合适、条件发生类型转换或函数计算;应结合 key、rows 和完整条件一起排查。
-
374 收藏
-
180 收藏
-
499 收藏
-
384 收藏
-
184 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习