Przetwarzanie dużych ilości danych w SQL wymaga szczególnego podejścia, aby zapobiec przepełnieniu pamięci, blokadom i zapewnić stabilną wydajność. Jedną z głównych technik jest podział operacji na wsady: dane wejściowe przetwarzane są w małych porcjach, co zmniejsza obciążenie serwera i pozwala lepiej kontrolować transakcje oraz rollbacki w przypadku błędów.
Kluczowe aspekty:
ROWCOUNT lub LIMIT / TOP)COMMIT, aby odciążyć dziennik transakcjiPrzykład (SQL Server):
DECLARE @BatchSize INT = 1000; WHILE 1 = 1 BEGIN BEGIN TRANSACTION; DELETE TOP(@BatchSize) FROM BigLogTable WHERE CreatedDate < '2021-01-01'; IF @@ROWCOUNT = 0 BREAK; COMMIT TRANSACTION; END
Jak usunąć 100 milionów rekordów z dużej tabeli z minimalnym wpływem na wydajność?
Niepoprawna odpowiedź: "Zrobić jedno duże DELETE".
Poprawna odpowiedź: Usuwać porcjami (wsadami) z kontrolą wielkości wsadu, robić COMMIT po każdym bloku, w razie potrzeby zmniejszać obciążenie dysku i blokady przy pomocy pauz (WAITFOR DELAY lub odpowiednik).
Przykład (PostgreSQL):
DO $$ BEGIN LOOP DELETE FROM big_table WHERE created_at < NOW() - interval '1 year' LIMIT 10000; EXIT WHEN NOT FOUND; COMMIT; END LOOP; END$$;
Historia
Projekt: Wysokowydajna usługa bankowa. Błąd: Programista uruchomił usunięcie przestarzałych logów jednym dużym zapytaniem na 80 mln wierszy. W rezultacie dziennik transakcji urósł do terabajtów, zapełniło to całe dostępne miejsce na dysku, a usługa "padła".
Historia
Projekt: Sklep internetowy z systemem magazynowym. Błąd: Podczas masowego wstawiania nie ograniczono rozmiaru transakcji. W trakcie importu masowych wsadów rekordy zakończyły się błędami, całą wcześniejszą pracę trzeba było wycofać i powtarzać, zajęło to godziny zamiast minut.
Historia
Projekt: Detalista, raportowa baza danych szczegółów zamówień. Błąd: Używano wsadów, ale zapomniano o COMMIT pomiędzy iteracjami — dziennik transakcji rósł Eksponencjalnie, serwer zaczął "zwalniać", a następnie wymagana była pilna konserwacja dzienników przy użyciu standardowych narzędzi.