Bulk UPDATE — критичная процедура при изменении большого числа строк по связанным таблицам. В истории SQL типичная реализация — UPDATE с подзапросом или JOIN. Проблема: любая массовая операция обновления без контроля порядка выполнения блокирует множество строк, вызывает эскалацию блокировок и может привести к deadlock при множественных обновлениях.
Решение:
Пример кода (PostgreSQL):
UPDATE Orders o SET status = 'archived' FROM Customers c WHERE o.customer_id = c.id AND c.closed = TRUE AND o.status != 'archived';
Или пакетно:
WITH upd AS ( SELECT o.id FROM Orders o JOIN Customers c ON o.customer_id = c.id WHERE c.closed = TRUE AND o.status != 'archived' LIMIT 10000 ) UPDATE Orders SET status = 'archived' WHERE id IN (SELECT id FROM upd);
Ключевые особенности:
Что произойдет, если одновременно запустить UPDATE схожих таблиц без разделения диапазонов или встречных фильтров?
Вероятно возникновение deadlock: процессы блокируют одни и те же строки, ожидая друг друга. Для избежания — пакеты должны не пересекаться или запускаться строго последовательно.
Есть ли разница между UPDATE через JOIN и подзапрос, если речь о массовой смене статуса?
Если есть подходящие индексы, ключевое отличие — только в читаемости и иногда в производительности конкретной СУБД. JOIN обычно быстрее, т. к. позволяет оптимизатору составить лучший план.
Когда актуально использовать TRUNCATE/DELETE вместо UPDATE?
Если бизнес-логика допускает — например, требуется физически удалить архивные записи или обнулить таблицу, а не просто поменять флаг статуса. Но для массового обновления статуса — только UPDATE.
В большом интернет-магазине запускали множественные UPDATE для смены статуса заказов и покупателей одновременно, без деления по intervу'lam. Итог: взаимные блокировки, несколько раз понадобился принудительный откат и откатились незаписанные данные.
Плюсы:
Минусы:
Большие выборки бились на батчи, запускались строго последовательно, обрабатывались только необходимые строки по фильтру.
Плюсы:
Минусы: