Оптимизация удаления анти-объединения SQL - PullRequest
0 голосов
/ 07 ноября 2018

У меня есть две таблицы в базе данных postgres, posts и users. posts имеет внешний ключ user_id, который ссылается на столбец первичного ключа users.id. Обе таблицы очень большие.

Я только что удалил случайный набор пользователей (около 80% от общего числа пользователей), и я хочу удалить все посты, которые ссылаются на удаленных пользователей, эффективно против объединения и удаления. Какой самый эффективный способ сделать это?

В настоящее время у меня есть это:

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

Есть ли более эффективный способ сделать это?

Ответы [ 2 ]

0 голосов
/ 08 ноября 2018

Если вы хотите удалить 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;

Пакетные вставки намного меньше работают, чем обновление большинства строк в таблице. Конечно, вы должны проверить это тщательно. Усечение таблицы - это быстрый способ удалить из нее все строки.

0 голосов
/ 07 ноября 2018

Кто-то на этой ссылке провел некоторое тестирование "не существует", "не существует", "против левого соединения-это-ноль". Postgre может сказать, что несуществующее и левое соединение равно нулю, являются анти-соединениями, и поэтому происходит соответственно. Так что ваш метод должен быть наиболее эффективным. Возможно, вы могли бы реструктурировать подход «оставайся равнодушным», но он, вероятно, ничего не купит.

Профилактика может быть лучше. Ограничение внешнего ключа - лучший вариант с удалением каскада. Вы упоминаете в комментариях к вашему вопросу, что это не вариант. Разве это не вариант в ваших конкретных обстоятельствах, потому что, как правило, это:

REFERENCES someTable(someCol) ON DELETE CASCADE ON UPDATE CASCADE
...