Najbardziej wydajny sposób na dodanie kolumny szeregowej do ogromnej tabeli


10

Jaki jest najszybszy sposób dodania kolumny BIGSERIAL do ogromnej tabeli (~ 3 Bil. Wierszy, ~ 174 Gb)?

EDYTOWAĆ:

  • Chcę, aby kolumna zwiększała wartości dla istniejących wierszy ( NOT NULL).
  • Nie ustawiłem współczynnika wypełnienia (co z perspektywy wygląda na złą decyzję).
  • Nie mam problemu z miejscem na dysku, po prostu chcę, aby było tak szybkie, jak to możliwe.

Odpowiedzi:


12

Co jest źle z:

ALTER TABLE foo ADD column bar bigserial;

Zostaną automatycznie wypełnione unikatowymi wartościami (zaczynając od 1).

Jeśli chcesz numer dla każdego istniejącego wiersza, każdy wiersz w tabeli musi zostać zaktualizowany . Czy nie?

Tabela zostanie powiększona do dwukrotnego rozmiaru, jeśli nie będzie mogła ponownie użyć martwych krotek lub wolnego miejsca na stronach danych. Wydajność operacji może przynieść wiele korzyści z FILLFACTORmniejszej niż 100 lub po prostu losowych martwych krotek rozłożonych na stole. W przeciwnym razie możesz chcieć uruchomić VACUUM FULL ANALYZEpóźniej, aby odzyskać miejsce na dysku. Nie będzie to jednak szybkie.

pgstattuple
Możesz być zainteresowany tym rozszerzeniem. Pomaga zbierać statystyki na stołach. Aby dowiedzieć się o martwych krotkach i wolnym miejscu:

Zainstaluj rozszerzenie raz na dane:

CREATE EXTENSION pgstattuple;

Połączenie:

SELECT * FROM pgstattuple('tbl');

Alternatywny

Jeśli możesz sobie pozwolić na stworzenie nowej tabeli, która zepsuje zależne widoki, klucze obce, ...

Utwórz pustą kopię starej tabeli:

CREATE new_tbl AS
SELECT *
FROM   old_tbl
LIMIT  0;

Dodaj kolumnę bigserial:

ALTER new_tbl ADD column bar bigserial;

WSTAW dane ze starej tabeli, automatycznie wypełniając bigserial:

INSERT INTO new_tbl
SELECT *    --  new column will be filled with default
FROM   old_tbl
ORDER  BY something; -- or don't order if you don't care: faster

W kolumnie WYBIERZ WSTAW brak nowej kolumny bigserial i zostanie ona automatycznie wypełniona jej wartością domyślną . Możesz przeliterować wszystkie kolumny i dodać nextval()do SELECTlisty, aby uzyskać ten sam efekt.

Upewnij się, że masz wszystkie dane w nowej tabeli.
Dodaj indeksy, ograniczenia, wyzwalacze miałeś na starym stole teraz .

DROP TABLE old_tbl;
ALTER TABLE new_tbl RENAME TO old_tbl;

Ogólnie może być nieco szybszy. To pozostawia waniliowy stół (i indeksy) bez wzdęć.

Potrzebujesz wolnego miejsca na dysku - mniej więcej wielkości starego stołu, w zależności od jego stanu - jako miejsca do poruszania się. Ale możesz potrzebować tyle samo z pierwszą prostą metodą ze względu na rozdęcie stołu. Ponownie szczegóły zależą od stanu twojego stołu.


3
Zawiń alternatywę w jedną transakcję, która będzie znacznie szybsza. Pozwoli to uniknąć dodatkowych fsyncs
Frank Heikens,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.