2013-05-31 210 views
3

我有两个表:食物和moos。mySQL删除查询优化

  • FOOS被索引的起始日期
  • 莫斯已经foos.id作为外键

FOOS非常大(数百万条记录)。 moos不是(10万条记录)。

我需要做一些相当简单的事情:从foos中删除记录,其中start_date为< 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,让我知道与起始日期< X穆斯的数量并不大(<> 200/300K记录)

  • 只有几千莫斯引用富

  • 我在MySQL 5.5,所以我不能解释一下“删除”,但是当我通过更换“选择1”的解释表明,MySQL是做什么我以为它会:

    • 首次使用起始日期指数找到合适的Foo
    • 再看看穆斯 所以它不应该是这样的“长”的交易...

有没有更好的方式来做到这一点,还是我失去了一些东西?

感谢,

PJ

+0

moos.foo_id为空?为什么加入空字段 –

+0

我不确定我遵循 - 这是一个左连接,所以它不应该是一个问题,应该吗? – PJC

+0

start_date上有索引吗? – neutrino

回答

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" 
    ); 

然后删除原始表,并重新命名新来的Foo。另外加上任何指标当然。

+0

谢谢乔治。但我不确定它会好得多 - 它意味着复制数百万条记录... – PJC

+0

如果您有足够的空间进行实验,值得一试,据我所知,这种方法允许更多的顺序写入,而不是随机的写入快点。 – George

0

另一种思考:

,如果这样做级联删除的外键可能是问题的每一个从Foo删除它也必须检查哞,看看现在有任何孤立记录。是的,它不应该只是因为你只删除了不匹配的,但查询计划者可能不那么聪明。

+0

是的,必须有查询计划器的东西。我想我需要尝试找到一个5.6安装来解释删除查询。 – PJC

0

查询#1将不起作用,因为foos.id = moos.foo_id仅在moos.foo_id不为NULL时才有效。 NULL与false中包含NULL的任何结果相比较。并且添加and moos.foo_id is null将导致没有匹配条件的记录。

我没有看到任何查询#2的原因不起作用。 select foo_id from moos where foo_id is not null运行多久?我会在那里添加distinct

查询#2也可以改写像

delete foos FROM foos 
WHERE start_date < "2013-05-30" 
    AND exists (select foo_id from moos where foo_id = foos.id); 
+0

谢谢Victor。虽然你的第一条评论:我很确定它的工作原理,因为它是一个左连接。在这里例如:http://www.w3schools.com/sql/sql_join_left.asp – PJC

+0

呃,是的,它将适用于外连接。请让我知道子查询运行时间,并做了我的查询工作。 –

0

我最终添加索引对foo_id的穆斯表,并解决了这个问题。 我不知道为什么有必要说实话(考虑到Moos不是一张大桌子)...

感谢所有花时间帮忙。

PJ