Просто DELETE
.Забудьте курсор.
Если ваша таблица огромная и вы удаляете большой процент строк, нет смысла делать это в пакетах.И даже тогда нет смысла.Единственные причины, по которым я могу придумать, - разрешить VACUUM
удалять мертвые кортежи раньше, что может помочь в особых случаях.Или чтобы избежать конфликта блокировок (возможны взаимоблокировки?), Но возникает вопрос, почему строки, которые должны быть удалены, должны быть заблокированы одновременными транзакциями.
Блокировки на строку для этого,Нет конфликта с одновременными INSERT
или UPDATE
до различными строками.(Если у вас есть ОБНОВЛЕНИЯ, нацеленные на одни и те же строки, у вас есть большая проблема.) И писатели не блокируют читателей в любом случае на Postgres.
Вы можете создайте курсор SQL с параметром WITH HOLD
, а затем используйте его с DELETE ... WHERE CURRENT OF
в отдельных транзакциях.Но вам придется добавить FOR UPDATE
, блокируя все затронутые строки в любом случае.Редко имеет смысл, за исключением случаев, когда вы хотите быстро заблокировать все затронутые строки, но по-прежнему что-то делать с ними перед удалением, и могут быть более разумные способы ...
Может иметь смысл разделить большую UPDATE
- вотдельные транзакции - так, чтобы мертвые кортежи можно было повторно использовать в обновлениях HOT (после ручного запуска VACUUM
или автоматического включения вакуума).Но это вряд ли относится к DELETE
операциям, которые не используют пространство повторно.Кроме того, DELETE
намного быстрее, чем UPDATE
.
В маловероятном событии , которое вам все еще нужно сделать в пакетном режиме, все равно не используйте курсор.Используйте что-то вроде:
WITH cte AS (
SELECT id -- your PK
FROM tbl
WHERE date < $something -- your condition
-- ORDER BY ??? -- optional, see below
LIMIT 50000
FOR UPDATE -- SKIP LOCKED ?
)
DELETE FROM tbl
USING cte
WHERE tbl.id = cte.id;
Повторяйте до тех пор, пока строки не будут найдены.
Если ваши данные (в основном) физически отсортированы определенным образом, они могут заплатить за заказ строк соответственно (в кавычках)ORDER BY
).ORDER BY
накладывает свою цену, но каждый DELETE
может иметь доступ к гораздо меньшему количеству страниц данных с кластеризованными строками и быстрее работать таким образом.Зависит от варианта использования;если ORDER BY
может использовать индекс, прогноз лучше.
См .: