Korzystanie z PG 9.1 na Ubuntu 12.04.
Obecnie uruchomienie dużego zestawu instrukcji UPDATE w bazie danych, które mają postać:
UPDATE table
SET field1 = constant1, field2 = constant2, ...
WHERE id = constid
(Po prostu nadpisujemy pola obiektów identyfikowanych przez identyfikator.) Wartości pochodzą z zewnętrznego źródła danych (jeszcze nie w DB w tabeli).
Tabele zawierają garść indeksów i nie ma ograniczeń klucza obcego. Do końca nie jest wykonywany COMMIT.
Zaimportowanie pg_dump
całego DB zajmuje 2 godziny. To wydaje się punktem odniesienia, do którego powinniśmy rozsądnie dążyć.
Czy poza stworzeniem niestandardowego programu, który w jakiś sposób rekonstruuje zestaw danych, aby PostgreSQL mógł ponownie zaimportować, czy jest coś, co możemy zrobić, aby zbliżyć masową wydajność UPDATE do wydajności importu? (Jest to obszar, który naszym zdaniem obsługuje drzewa scalające o strukturze dziennika, ale zastanawiamy się, czy jest coś, co możemy zrobić w PostgreSQL.)
Jakieś pomysły:
- porzucasz wszystkie wskaźniki inne niż ID, a potem odbudowujesz?
- zwiększenie checkpoint_segments, ale czy to faktycznie pomaga w utrzymaniu długoterminowej przepustowości?
- używając technik wymienionych tutaj ? (Załaduj nowe dane jako tabelę, a następnie „scal” stare dane, w których nie znaleziono identyfikatora w nowych danych)
Zasadniczo jest wiele rzeczy do wypróbowania i nie jesteśmy pewni, jakie są najbardziej skuteczne lub czy pomijamy inne rzeczy. Kolejne dni spędzimy na eksperymentach, ale pomyśleliśmy, że też tutaj zapytamy.
Mam równoległe obciążenie tabeli, ale jest to tylko do odczytu.
explain analyze
to, że używa indeksu do wyszukiwania?Odpowiedzi:
Założenia
Ponieważ w Q brakuje informacji, założę:
COPY
dane wyjściowe, z unikalnymid
wierszem pasującym do tabeli docelowej.Jeśli nie, najpierw sformatuj go poprawnie lub użyj
COPY
opcji, aby poradzić sobie z tym formatem.Oznacza to brak równoczesnego dostępu. W przeciwnym razie rozważ tę powiązaną odpowiedź:
Rozwiązanie
Sugeruję, aby stosować podobne podejście, jak opisano w linku z trzeciej kuli . Z dużymi optymalizacjami.
Aby utworzyć tabelę tymczasową, istnieje prostszy i szybszy sposób:
Jeden duży
UPDATE
z tabeli tymczasowej wewnątrz bazy danych będzie szybsza niż poszczególnych aktualizacjach spoza bazy danych o kilka rzędów wielkości.W modelu PostgreSQL MVCC , an
UPDATE
środki, aby utworzyć nową wersję wiersza i oznaczyć starą jako usunięte. To jest tak drogie jakINSERT
iDELETE
łącznie. Plus, pozostawia ci wiele martwych krotek. Ponieważ i tak aktualizujesz cały stół, ogólnie byłoby szybsze utworzenie nowego stołu i upuszczenie starego.Jeśli masz wystarczającą ilość pamięci RAM, ustaw
temp_buffers
(tylko dla tej sesji!) Wystarczająco wysoką, aby utrzymać tabelę temp w pamięci RAM - zanim zrobisz cokolwiek innego.Aby oszacować, ile pamięci RAM jest potrzebne, uruchom test z małą próbką i użyj funkcji rozmiaru obiektu db :
Kompletny skrypt
Równoczesne obciążenie
Współbieżne operacje na tabeli (które wykluczyłem w założeniach na początku) będą czekać, gdy tabela zostanie zablokowana pod koniec i zakończy się niepowodzeniem, gdy transakcja zostanie zatwierdzona, ponieważ nazwa tabeli jest natychmiast rozpoznawana jako OID, ale nowa tabela ma inny identyfikator OID. Tabela pozostaje spójna, ale równoczesne operacje mogą uzyskać wyjątek i muszą zostać powtórzone. Szczegóły w tej powiązanej odpowiedzi:
AKTUALIZUJ trasę
Jeśli (musisz) przejść
UPDATE
trasę, upuść indeks, który nie jest potrzebny podczas aktualizacji, a następnie utwórz go ponownie. Znacznie taniej jest utworzyć indeks w jednym kawałku niż zaktualizować go dla każdego wiersza. Może to również pozwolić na GORĄCE aktualizacje .Przedstawiłem podobną procedurę
UPDATE
w tej ściśle powiązanej odpowiedzi dotyczącej SO .źródło
DROP TABLE
bierze sięAccess Exclusive Lock
. Tak czy inaczej, na początku mojej odpowiedzi wymieniłem warunek wstępny:You can afford to drop and recreate the target table.
może pomóc zablokować tabelę na początku transakcji. Sugeruję, aby rozpocząć nowe pytanie ze wszystkimi istotnymi szczegółami swojej sytuacji, abyśmy mogli przejść do sedna tego.CREATE TABLE tbl_new AS SELECT t.*, u.field1, u.field2 from tbl t NATURAL LEFT JOIN tmp_tbl u;
,LEFT JOIN
pozwalając zachować wiersze, dla których nie ma aktualizacji. OczywiścieNATURAL
można zmienić na dowolny ważnyUSING()
lubON
.Jeśli dane można udostępnić w pliku strukturalnym, można je odczytać za pomocą zewnętrznego opakowania danych i wykonać scalenie w tabeli docelowej.
źródło
MERGE
nie jest jeszcze zaimplementowany w PostgreSQL (jeszcze). Implementacje w innych RDBMS są dość różne. Rozważ informacje o tagach dlaMERGE
iUPSERT
.