MySQL从多个表中查找缺失值的最有效方法

时间:2012-07-12 09:50:31

标签: mysql

我有三个表,第一个是电子邮件地址列表:

addresses:
id - integer, this is the primary key<br>
email - varchar(255) field holding the address

sent:
sid - integer, foreign key references id in addresses table

received:
rid - integer, foreign key references id in addresses table

显然,“已发送”和“已接收”表有其他列,但它们对此问题并不重要。每次发送或接收电子邮件时都会填充已发送和已接收的表,如果该地址不在“地址”表中,则会添加该表。表格可以变得非常大(100,000 +)。

定期清除“已发送”和“已接收”表的条目,并因各种原因删除条目,将“孤立”条目留在“地址”表中。

我正在寻找MySQL中最有效的方法来清除“地址”表中的孤立条目。我到目前为止的查询是:

delete 
from addresses 
where id not in 
         (select rid from received) 
  and id not in 
         (select sid from sent);

这样可行,但可能需要一段时间才能运行,绝对不是最有效的方法!我也试过这个:

delete 
from addresses 
where not exists 
      (select 'x' from sent where sent.sid=addresses.id) 
  and not exists 
      (select 'x' from rceieved where recieved.rid=addresses.id);

这有点快,但仍然需要很长时间,我怀疑我需要使用JOIN语法,但此时我的sql知识已经用完了!

4 个答案:

答案 0 :(得分:1)

这应该可以解决问题

DELETE adresses.* FROM adresses 
LEFT JOIN sent ON sent.sid=adresses.id
LEFT JOIN received ON received.rid=adresses.id
WHERE sent.sid IS NULL AND received.rid IS NULL

答案 1 :(得分:0)

试试这个: 从地址中删除左连接发送的s on(a.sentid = s.id)其中s.id为空

答案 2 :(得分:0)

对不起,我真的无法给出明确的答案。但我遇到了类似的问题,在环顾四周之后,似乎只有两个主要选择:

  1. 使用WHERE x NOT IN y
  2. 使用LEFT JOIN x ON y WHERE z IS NULL
  3. 我通过分别比较2822291和916626记录的两个表来尝试这两种方法。

    表现结论如下:

    • 类型1 明显更快比类型2(600秒对6000秒)
    • 索引或键对这两种类型的操作的性能都有合理的影响。
    • 性能几乎与实际的DISTINCT值无关。因此,比较两个表的2000个不同值或仅15个大约相同的时间。

    因此,截至目前(08-2013),似乎选项1仍然是更快的方式。使用NOT EXISTS可能会更快,但与类型1相比,性能变化并不显着。

    我希望这最终可以帮助任何人。

答案 3 :(得分:0)

使用2个300k myisam表进行了一些测试,其中包含2个id列(以及其他几个不相同的列)。除了一个表中的2个记录外,ID是相同的。尝试了提到的3种方法来找到这些ID:

不存在

LEFT JOIN

IN()

确保使用SQL_NO_CACHE并执行相同的所有查询,服务器在~14.6秒内返回两个结果。

上述差异必须是缓存,不同版本的mysql和/或一般服务器配置。