Bulk UPDATE to krytyczna procedura podczas zmiany dużej liczby wierszy w powiązanych tabelach. W historii SQL typowa realizacja — UPDATE z podzapytaniem lub JOIN. Problem: każda masowa operacja aktualizacji bez kontroli kolejności wykonania blokuje wiele wierszy, powoduje eskalację blokad i może prowadzić do deadlocku przy wielu aktualizacjach.
Rozwiązanie:
Przykład kodu (PostgreSQL):
UPDATE Orders o SET status = 'archived' FROM Customers c WHERE o.customer_id = c.id AND c.closed = TRUE AND o.status != 'archived';
Lub pakietowo:
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);
Kluczowe cechy:
Co się stanie, jeśli jednocześnie uruchomimy UPDATE podobnych tabel bez podziału zakresów lub przeciwstawnych filtrów?
Prawdopodobnie wystąpi deadlock: procesy blokują te same wiersze, czekając na siebie nawzajem. Aby tego uniknąć — pakiety nie powinny się pokrywać lub być uruchamiane ścisłe kolejno.
Czy istnieje różnica między UPDATE przez JOIN a podzapytaniem, jeśli chodzi o masową zmianę statusu?
Jeśli są odpowiednie indeksy, kluczowa różnica polega tylko na czytelności i czasami wydajności konkretnego DBMS. JOIN jest zazwyczaj szybszy, ponieważ pozwala optymalizatorowi stworzyć lepszy plan.
Kiedy warto używać TRUNCATE/DELETE zamiast UPDATE?
Jeśli logika biznesowa na to pozwala — na przykład, gdy wymagana jest fizyczna eliminacja archiwalnych zapisów lub zerowanie tabeli, a nie tylko zmiana flagi statusu. Ale do masowej aktualizacji statusu — tylko UPDATE.
W dużym sklepie internetowym uruchomiono wielokrotne UPDATE w celu zmiany statusu zamówień i klientów jednocześnie, bez podziału według intervu'lam. Efekt: wzajemne blokady, kilka razy konieczne było wymuszenie rollbacku, a niezapisane dane zostały utracone.
Zalety:
Wady:
Duże zbiory dzielono na partie, uruchamiano ściśle kolejno, przetwarzano tylko potrzebne wiersze według filtru.
Zalety:
Wady: