【问题标题】:SQL Anti-join Delete OptimisationSQL 反连接删除优化
【发布时间】:2019-04-11 04:01:42
【问题描述】:

我在 postgres 数据库中有两个表,posts 和 users。 posts 有一个引用 users.id 主键列的 user_id 外键。两张表都很大。

我刚刚删除了一组随机用户(约占总用户的 80%),我想删除所有引用已删除用户的帖子,实际上是反加入和删除。最有效的方法是什么?

目前我有这个:

DELETE FROM posts l
WHERE NOT EXISTS
  (
     SELECT NULL
     FROM users r
     WHERE r.id = l.user_id
  )

有没有更有效的方法?

【问题讨论】:

  • 如果您要删除大量用户,那么您可能需要创建一个新表,其中包含仍处于活动状态的帖子。
  • 当然最好的选择是在删除用户的同时删除帖子。您的 DBMS 甚至可以使用某种参照完整性系统自动执行此操作...
  • @GordonLinoff 是的,这很好。说为了争论,我删除了 80% 的用户(我已经更新了问题以反映这个前提)。
  • @JeffUK 级联删除不是一个选项。

标签: sql postgresql anti-join


【解决方案1】:

如果你想删除80%的用户,那么最快的方法大概是:

create table temp_posts as 
    select p.*
    from posts p
    where exists (select 1 from users u where u.id = p.user_id);

truncate table posts;

insert into posts
    select *
    from temp_posts;

与更新表中的大多数行相比,批量插入的工作量要少得多。当然,您应该仔细测试。截断表格是从表格中删除所有行的快速方法。

【讨论】:

    【解决方案2】:

    this 链接上的某人对不存在、不存在和 left-join-is-null 进行了一些测试。 Postgre 可以判断不存在和左连接为空是反连接,因此继续进行。所以你的方法应该是最有效的。您可能会重组为 left-join-is-null 方法,但它可能不会给您带来任何好处。

    预防可能会更好。外键约束是更好的选择,具有级联删除功能。您在 cmets 中提到您的问题,这不是一个选项。在您的特定情况下,这不是一个选项吗,因为通常,它是:

    REFERENCES someTable(someCol) ON DELETE CASCADE ON UPDATE CASCADE
    

    【讨论】:

      猜你喜欢
      • 2015-03-10
      • 1970-01-01
      • 2018-10-30
      • 2012-06-28
      • 2018-03-24
      • 1970-01-01
      • 1970-01-01
      • 2017-09-16
      • 1970-01-01
      相关资源
      最近更新 更多