Мне интересно, как наиболее эффективно было бы удалить большое количество строк из PostgreSQL, этот процесс будет частью повторяющейся задачи каждый день для массового импорта данных (дельта вставок + удалений) в таблицу. Могут быть тысячи, потенциально миллионы строк, которые нужно удалить.
У меня есть файл первичных ключей, по одному на строку. Два варианта, о которых я думал, соответствовали приведенному ниже, но я не знаю / не понимаю достаточно внутренних особенностей PostgreSQL, чтобы принять обоснованное решение, которое было бы наилучшим.
- Выполните
DELETE
запрос для каждой строки в файле с простымWHERE
первичным ключом (или сгруппируйте удаления в пакетах,n
используяIN()
предложение) - Импортируйте первичные ключи во временную таблицу с помощью
COPY
команды, а затем удалите из основной таблицы с помощью объединения
Любые предложения будут высоко оценены!
postgresql
delete
bulk
tarnfeld
источник
источник
Ответы:
Ваш второй вариант намного чище и будет работать достаточно хорошо, чтобы это стоило того. Ваша альтернатива - создавать гигантские запросы, которые будет довольно сложно планировать и выполнять. В общем, вам лучше позволить PostgreSQL сделать всю работу здесь. В общем, я нашел обновления для десятков тысяч строк в порядке, который вы описываете для адекватной работы, но есть одна важная вещь, которую следует избегать.
Способ сделать это состоит в том, чтобы использовать выбор и объединение в вашем удалении.
Ни при каких обстоятельствах не следует делать следующее с большой таблицей:
Это обычно вызывает объединение вложенных циклов, что делает производительность довольно проблематичной. Если вам в конечном итоге придется идти по этому пути, сделайте это вместо:
PostgreSQL, как правило, довольно хорошо избегает плохих планов, но все же есть случаи, связанные с внешними объединениями, которые могут иметь большое значение для хороших и плохих планов.
Это немного дальше, но я полагаю, что стоит упомянуть, потому что легко перейти от IN к NOT IN и наблюдать за производительностью запросов.
источник
IN ( select id from foo except select id from rows_to_keep )
см postgresql.org/docs/9.4/static/queries-union.htmlЯ столкнулся с этим вопросом, потому что у меня была похожая проблема. Я очищаю базу данных с 300M + строками, итоговая база данных будет содержать только около 30% исходных данных. Если вы сталкиваетесь с подобным сценарием, на самом деле легче вставить новую таблицу и переиндексировать, а не удалять.
Сделать что-то вроде
При правильном индексировании по foo и bar вы можете избежать сканирования Seq.
Тогда вам придется переиндексировать и переименовать таблицу.
источник