MySQL DELETE子查询执行超时报2013错误的替代实现方案咨询
MySQL DELETE操作性能优化方案
原语句超时原因
单独执行SELECT子查询时仅需单次计算即可得到结果,但MySQL对DELETE语句中的IN子查询优化能力较差,优化器会将其改写为相关子查询:外层表每一行都会触发一次子查询匹配,数据量较大时会出现锁持有时间过长、连接中断的问题。
最优实现方案:多表关联DELETE
直接用JOIN代替IN子查询,仅需单次计算待删除ID列表即可完成匹配,同时简化了子查询逻辑,性能提升非常明显:
DELETE t1 FROM `table` t1 INNER JOIN ( SELECT id_facture FROM `table` GROUP BY id_facture HAVING COUNT(DISTINCT num_commande) > 1 ) t2 ON t1.id_facture = t2.id_facture;
该方案完全匹配需求:针对示例数据,子查询会筛选出关联了多个不同num_commande的id_facture(1和3),关联后会删除这两个ID对应的所有行,仅保留id_facture=2的行。
超大表场景优化方案
如果表数据量超过百万级,可通过临时表中转的方式进一步降低锁持有时间,避免影响线上业务:
-- 创建临时表存储待删除的ID CREATE TEMPORARY TABLE tmp_del_ids ( id_facture INT PRIMARY KEY ); -- 写入待删除的ID列表 INSERT INTO tmp_del_ids SELECT id_facture FROM `table` GROUP BY id_facture HAVING COUNT(DISTINCT num_commande) > 1; -- 关联执行删除 DELETE t1 FROM `table` t1 INNER JOIN tmp_del_ids t2 ON t1.id_facture = t2.id_facture; -- 清理临时表(会话结束也会自动释放) DROP TEMPORARY TABLE IF EXISTS tmp_del_ids;
额外性能优化建议
- 给
(id_facture, num_commande)创建联合索引,可让分组统计和关联匹配都直接走索引,性能提升数倍 - 若数据量极大,可在删除时加LIMIT分批执行,比如每次删除1000条,避免长时间锁表
内容的提问来源于stack exchange,提问作者thomas
相关产品推荐
相关产品推荐

