我有两张桌子:食物和moos。
foos非常大(数百万条记录)。 moos不是(100k记录)。
我需要做一些相当简单的事情:使用start_date<删除来自foos的记录X并没有在moos中引用。我希望这不是一个特定的问题,但我无法让它工作(它永远挂起)我尝试了我认为将是“通常”的方式:
delete foos FROM foos LEFT JOIN moos ON foos.id = moos.foo_id WHERE moos.foo_id is null AND foos.start_date < "2013-05-30";
delete foos FROM foos WHERE start_date < "2013-05-30" AND id NOT IN (select foo_id from moos where foo_id is not null);
我应该补充:
我总是选择X,以便通过start_date&lt;知道moos的数量。 X不大(&lt;> 200 / 300k记录)
只有几千个moos引用了foo
我在mySQL 5.5上,所以我无法解释“删除”,但当我用“select 1”替换时,解释建议mySQL正在做我想的那样:
有更好的方法可以做到这一点,还是我错过了什么?
谢谢,
PJ
答案 0 :(得分:0)
怎么样......
CREATE TABLE foos_new
SELECT *
FROM
foos
LEFT JOIN moos on foos.id = moos.foo_id
WHERE
moos.foo_id IS NOT NULL
OR
(
moos.foo_id IS NULL AND
foos.start_date >= "2013-05-30"
);
然后DROP原始表并将新表重命名为foos。另外,当然还要添加任何索引。
答案 1 :(得分:0)
另一个想法:
如果对foo中的每次删除执行级联删除,外键可能是问题,它还必须检查moo以查看是否存在任何孤立记录。是的,它不需要,因为你只是删除不匹配的,但查询计划可能不那么聪明。
答案 2 :(得分:0)
查询#1不起作用,因为foos.id = moos.foo_id
仅在moos.foo_id
不为NULL时才有效。与false
中包含NULL的任何内容相比,NULL为NULL。添加and moos.foo_id is null
将导致没有符合条件的记录。
我认为查询#2无法正常工作。 select foo_id from moos where foo_id is not null
会运行多长时间?我会在那里添加distinct
BTW。
查询#2也可以像
一样重写delete foos FROM foos
WHERE start_date < "2013-05-30"
AND exists (select foo_id from moos where foo_id = foos.id);
答案 3 :(得分:0)
我最终在foo_id上添加了一个Moos表的索引,它解决了这个问题。 我不确定为什么必须诚实(考虑到Moos不是一张大桌子)......
感谢所有人花时间提供帮助。
PJ