SQL:删除其关联被破坏的行(孤立数据)

时间:2011-05-14 14:04:45

标签: sql

我有一个名为“downloads”的表,其中包含两个外键列 - “user_id”和“item_id”。我需要从该表中选择所有行,并删除有问题的User或Item不再存在的行。 (查找用户,如果找不到,请删除“下载”中的行,然后查找项目,如果找不到,请删除“下载”中的行。

这是340万行,所以我所有的脚本解决方案都需要6个多小时。我希望有一种更快的,只有SQL的方法来做到这一点?

5 个答案:

答案 0 :(得分:26)

使用两个反连接和or它们在一起:

delete from your_table
where user_id not in (select id from users_table)
or item_id not in (select id from items_table)

完成后,请考虑添加两个外键,每个外键都有一个on delete cascade子句。它会自动为你做这件事。

答案 1 :(得分:3)

delete from your_table where user_id not in (select id from users_table) or item_id not in (select id from items_table)

答案 2 :(得分:0)

认为当行数太多时没有更快的解决方案 在您的服务器上每秒157行

检查用户ID 如果mysql num rows = 0,则删除下载并检查item_id

还有一个关于myswl num rows

性能的类似问题

MySQL: Fastest way to count number of rows

编辑:认为最好是创建一些触发器,以便数据库服务器为您完成工作

目前我第一次使用cronjob

答案 3 :(得分:0)

供将来参考。对于这种长期操作。可以独立于SQL优化服务器。例如,如果可以确保sql日志文件位于数据库所在的驱动器的单独磁盘驱动器上,则分离sql服务,对系统磁盘进行碎片整理。 这至少可以减轻这些长时间操作的痛苦。

答案 4 :(得分:0)

我在SQL 2008 R2中发现,如果你的“in”子句包含一个空值(可能来自一个引用该键可以为空的表),则不会返回任何记录!要更正,只需在union部分的选择中添加一个子句:

delete from SomeTable where Key not in (
  select SomeTableKey from TableB where SomeTableKey is not null
  union
  select SomeTableKey from TableC where SomeTableKey is not null
)