Muszę zaktualizować tabele z 1 lub 2 miliardami wierszy z różnymi wartościami dla każdego wiersza. Każde uruchomienie powoduje ~100 milionów zmian (10%). Moją pierwszą próbą było zgrupowanie ich w transakcji 300K aktualizacji bezpośrednio na określonej partycji, ponieważ Postgresql nie zawsze optymalizuje przygotowane zapytania, jeśli używasz partycji.
- Transakcje z grupy „UPDATE mojaTabela SET myField=value WHEREmyId=id”
Daje 1500 aktualizacje/sek. co oznacza, że każdy bieg zajmie co najmniej 18 godzin. - Gorące rozwiązanie aktualizacyjne, jak opisano tutaj z FILLFACTOR=50. Daje 1600 aktualizacji na sekundę. Używam dysków SSD, więc jest to kosztowna poprawa, ponieważ podwaja rozmiar pamięci.
- Wstaw do tymczasowej tabeli zaktualizowanej wartości i połącz je później z UPDATE...FROM Daje 18 000 aktualizacje/sek. jeśli zrobię VACUUM dla każdej partycji; 100 000 w górę/s w przeciwnym razie. Super.
Oto następująca kolejność operacji:
CREATE TEMP TABLE tempTable (id BIGINT NOT NULL, field(s) to be updated,
CONSTRAINT tempTable_pkey PRIMARY KEY (id));
Zgromadź pakiet aktualizacji w buforze w zależności od dostępnej pamięci RAM, gdy jest zapełniony, gdy trzeba zmienić tabelę/partycję lub ukończono:
COPY tempTable FROM buffer;
UPDATE myTable a SET field(s)=value(s) FROM tempTable b WHERE a.id=b.id;
COMMIT;
TRUNCATE TABLE tempTable;
VACUUM FULL ANALYZE myTable;
Oznacza to, że 100 milionów aktualizacji zajmuje teraz 1,5 godziny zamiast 18 godzin, łącznie z próżnią. Aby zaoszczędzić czas, nie jest konieczne wykonanie PEŁNEGO odkurzania na końcu, ale nawet szybkie, regularne odkurzanie jest przydatne do kontrolowania identyfikatora transakcji w bazie danych i zapobiegania niepożądanemu automatycznemu odkurzaniu w godzinach szczytu.