SQL删除查询持续运行无报错问题求助
兄弟,看你这DELETE语句卡着跑不动,我太懂这种滋味了!结合你给的表数据量和未写完的SQL,大概率是嵌套子查询的性能坑加上可能没建索引的问题,给你捋捋怎么解决:
先搞清楚核心问题
你的SQL应该是想删除没有在liste_des_cours_has_cours关联表里出现过的cours记录对吧?但你用的多层嵌套IN子查询在12万级数据量下会特别慢:
- 多层
(select * from cours)会生成无索引的临时表,数据库要反复扫描这些临时表 NOT IN子查询在处理大数据集时,执行计划通常是低效的嵌套循环,相当于每条cours记录都要跑一遍子查询- 如果关联字段没建索引,还会触发全表扫描,12万×12万的扫描量肯定卡到天荒地老
第一步:先补全索引(最关键!)
先检查这两个索引有没有:
- 给
cours表的Id_cours加索引(如果它不是主键的话,主键自带索引):CREATE INDEX idx_cours_id ON cours(Id_cours); - 给
liste_des_cours_has_cours表的关联字段(对应cours.Id_cours的字段,比如cours_Id_cours)加索引:CREATE INDEX idx_lchc_cours_id ON liste_des_cours_has_cours(cours_Id_cours);
第二步:用更高效的写法替代嵌套子查询
推荐用LEFT JOIN替代NOT IN,不仅性能好,还能避免NOT IN遇到NULL值的坑:
MySQL写法:
DELETE c FROM cours c LEFT JOIN liste_des_cours_has_cours lchc ON c.Id_cours = lchc.cours_Id_cours -- 这里替换成你实际的关联字段名 WHERE lchc.cours_Id_cours IS NULL;
PostgreSQL写法(如果用的是PG):
DELETE FROM cours WHERE Id_cours NOT IN ( SELECT DISTINCT cours_Id_cours FROM liste_des_cours_has_cours WHERE cours_Id_cours IS NOT NULL );
(加DISTINCT是因为关联表里可能有重复的ID,去重后子查询结果更小,执行更快)
第三步:可选:分批删除避免锁表
如果一次性删除的记录太多,可能会锁表影响业务,建议分批删:
WHILE EXISTS ( SELECT 1 FROM cours c LEFT JOIN liste_des_cours_has_cours lchc ON c.Id_cours = lchc.cours_Id_cours WHERE lchc.cours_Id_cours IS NULL ) DO DELETE c FROM cours c LEFT JOIN liste_des_cours_has_cours lchc ON c.Id_cours = lchc.cours_Id_cours WHERE lchc.cours_Id_cours IS NULL LIMIT 1000; -- 每次删1000条,根据你的数据库性能调整数量 END WHILE;
按这个步骤来,应该很快就能跑完了!
内容的提问来源于stack exchange,提问作者firestormde3
相关产品推荐
相关产品推荐

