慢DELETE主因是未走索引导致全表扫描,应先用EXPLAIN分析执行计划;推荐分批删除(如MySQL按主键范围每次5000行)、避免大事务、慎用子查询,必要时物化中间结果。

DELETE WHERE 条件太多,执行慢得像卡住?先看执行计划
绝大多数慢 DELETE 不是语法问题,而是数据库没走索引,全表扫描删几万行就明显卡顿。别急着加索引,先用 EXPLAIN 看清实际执行路径。
- MySQL 里直接在
DELETE前加EXPLAIN(如EXPLAIN DELETE FROM orders WHERE status = 'pending' AND created_at ),重点看 <code>type是不是range或ref,key列有没有命中索引 - PostgreSQL 用
EXPLAIN (ANALYZE, BUFFERS),注意Rows Removed by Filter是否远大于Rows Removed by Index Recheck——前者高说明索引没覆盖所有条件,还得回表过滤 - WHERE 中用了函数(如
WHERE DATE(created_at) = '2023-01-01')或隐式类型转换(如字符串字段和数字比较),索引基本失效,必须改写
复合条件删数据,索引怎么建才不白搭
索引不是越多越好,关键要匹配 WHERE 中的列顺序和过滤强度。一个索引能否生效,取决于最左前缀是否被查询条件“连续使用”。
- 条件是
WHERE user_id = 123 AND status IN ('failed', 'timeout') AND updated_at ,推荐建联合索引:<code>CREATE INDEX idx_user_status_updated ON orders (user_id, status, updated_at) - 如果
status只有 3 个值,而user_id区分度极高,把user_id放最左才能快速定位到小范围数据;反过来把status放最左,可能扫出几百万行再筛user_id - 避免冗余索引:已有
(a, b, c),再建(a, b)意义不大;但(a, c)可能有用——如果查询常走WHERE a = ? AND c > ?且b不参与
大表删数据卡死或锁表?拆成小批量 + 控制事务粒度
一次性删几十万行,不仅慢,还容易阻塞其他读写、触发 long transaction 报警,甚至填满 binlog 或 WAL。真实生产环境几乎从不用单条大 DELETE。
- MySQL 推荐用
DELETE FROM orders WHERE id BETWEEN ? AND ? AND status = 'archived',每次删 5000 行,用主键范围控制,避免LIMIT在无序字段上导致重复或遗漏 - PostgreSQL 可用 CTE +
WITH deleted AS (DELETE ... RETURNING id) SELECT count(*) FROM deleted配合循环,但更稳的是用游标分页:WHERE id > last_seen_id ORDER BY id LIMIT 5000 - 务必在事务外做循环,每批单独提交;别包进一个大事务——否则 rollback 日志暴涨,锁持有时间翻倍
WHERE 里用了子查询,为什么索引突然不走了
子查询本身不难,但嵌套位置决定优化器能不能下推条件、复用索引。尤其 IN (SELECT ...) 和 EXISTS 行为差异极大。
-
DELETE FROM logs WHERE app_id IN (SELECT id FROM apps WHERE category = 'mobile'):MySQL 5.6+ 通常会转成 semi-join,但如果子查询结果集大或没索引,仍可能退化为对logs每行都跑一次子查询 - 换成
EXISTS写法:DELETE FROM logs l WHERE EXISTS (SELECT 1 FROM apps a WHERE a.id = l.app_id AND a.category = 'mobile'),更容易利用apps(id, category)索引 - 更稳妥的做法是先物化中间结果:
CREATE TEMP TABLE tmp_app_ids AS SELECT id FROM apps WHERE category = 'mobile'; CREATE INDEX ON tmp_app_ids(id);,再DELETE ... JOIN tmp_app_ids—— 明确可控
真正难的从来不是“怎么写 DELETE”,而是判断哪些条件能走索引、哪些必须改写、哪些得拆批次。很多线上慢删问题,查完 EXPLAIN 就定位了,剩下只是补索引或调参数的事——但跳过这步直接动手,大概率越改越慢。

















