Czy lepiej jest utworzyć indeks przed wypełnieniem tabeli danymi, czy po umieszczeniu danych?

87

Mam tabelę zawierającą około 100 milionów wierszy, które zamierzam skopiować, aby zmienić, dodając indeks. Nie interesuje mnie czas potrzebny na utworzenie nowej tabeli, ale czy utworzony indeks będzie bardziej wydajny, jeśli zmienię tabelę przed wstawieniem jakichkolwiek danych lub najpierw wstawię dane, a następnie dodam indeks?

Drew Stephens
źródło

Odpowiedzi:

113

Tworzenie indeksu po wstawieniu danych jest bardziej efektywnym sposobem (nawet często zaleca się usunięcie indeksu przed importem wsadowym i odtworzenie go po imporcie).

Przykład syntetyczny (PostgreSQL 9.1, wolna maszyna programistyczna, milion wierszy):

CREATE TABLE test1(id serial, x integer);
INSERT INTO test1(id, x) SELECT x.id, x.id*100 FROM generate_series(1,1000000) AS x(id);
-- Time: 7816.561 ms
CREATE INDEX test1_x ON test1 (x);
-- Time: 4183.614 ms

Wstaw, a następnie utwórz indeks - około 12 sek

CREATE TABLE test2(id serial, x integer);
CREATE INDEX test2_x ON test2 (x);
-- Time: 2.315 ms
INSERT INTO test2(id, x) SELECT x.id, x.id*100 FROM generate_series(1,1000000) AS x(id);
-- Time: 25399.460 ms

Utwórz indeks, a następnie wstaw - około 25,5 sekundy (ponad dwa razy wolniej)

walodzka
źródło
5
+1, indeksy znacznie spowolnią operację obejmującą zadanie wstawiania 100 mln wierszy, więc lepiej je porzucić i odtworzyć.
code4life
10

Prawdopodobnie lepiej jest utworzyć indeks po dodaniu wierszy. Nie tylko będzie to szybsze, ale prawdopodobnie wyważenie drzewa będzie lepsze.

Edycja „balansowania” prawdopodobnie nie jest tutaj najlepszym wyborem terminów. W przypadku drzewa b jest to z definicji zrównoważone. Ale to nie znaczy, że b-drzewo ma optymalny układ. Rozmieszczenie węzłów potomnych w rodzicach może być nierówne (co prowadzi do wyższych kosztów w przyszłych aktualizacjach), a głębokość drzewa może być większa niż jest to konieczne, jeśli równoważenie nie jest wykonywane ostrożnie podczas aktualizacji. Jeśli indeks zostanie utworzony po dodaniu wierszy, prawdopodobnie będzie miał lepszą dystrybucję. Ponadto strony indeksowe na dysku mogą mieć mniejszą fragmentację po utworzeniu indeksu. Trochę więcej informacji tutaj

Mark Wilkins
źródło
2

Nie ma to znaczenia w przypadku tego problemu, ponieważ:

  1. Jeśli dodasz dane najpierw do tabeli, a po niej dodasz indeks. Twój czas generowania indeksu będzie O(n*log(N))dłuższy (gdzie nzostaną dodane wiersze). Ponieważ czas trwania drzewa jest O(N*log(N))wtedy, gdy podzielisz to na stare dane i nowe dane, które otrzymasz, O((X+n)*log(N))można to po prostu przekonwertować na O(X*log(N) + n*log(N))iw tym formacie możesz po prostu zobaczyć, na co będziesz czekać.
  2. Jeśli dodasz indeks, a po nim umieścisz dane. Każdy wiersz (masz nnowe wiersze) dostajesz dłuższy czas wstawiania dodatkowego czasu O(log(N))potrzebnego na zregenerowanie struktury drzewa po dodaniu do niego nowego elementu (indeks kolumna z nowego wiersza, ponieważ indeks już istnieje i nowy wiersz został dodany to indeks musi zostać zregenerowany do zrównoważenia struktura, ten koszt O(log(P))gdzie Pjest mocą indeksu [elementy w indeksie] ). Masz nnowe wiersze w końcu trzeba n * O(log(N))potem O(n*log(N))Podsumowanie dodatkowego czasu.
Svisstack
źródło
1

Indeksy utworzone później są w większości przypadków znacznie szybsze. Przykład: 20 milionów wierszy z pełnym tekstem na varchar (255) - (nazwa firmy) Indeks na miejscu podczas importowania wierszy - dopasowanie do 20 sekund w najgorszych przypadkach. Upuść indeks i odtwórz ponownie - dopasuj, aby za każdym razem zajmować mniej niż 1 sekundę

Mike Cross
źródło
-2

Nie jestem pewien, czy będzie to miało znaczenie dla wydajności indeksu, ponieważ w obu przypadkach wstawiasz nowe dane do indeksu. Serwer nie wiedziałby, jak niezrównoważony byłby indeks, dopóki nie zostałby zbudowany. Jeśli chodzi o szybkość, oczywiście wstawki bez indeksu.

Grandmaster B.
źródło