Klastrowanie tabel

Operacja klastrowania służy takiemu rozłożeniu danych w tabeli, by wiersze mające te same wartości w wybranej zaindeksowanej kolumnie leżały obok siebie. Dzięki temu że dane są bliżej siebie, również odczytywanie ich będzie się odbywało szybciej. Wieść gminna niesie, że odczyty zakresowe i po wartości potrafią przyspieszyć nawet 20 krotnie! Twierdzenie to opieram na badaniach Hansa Hasselberga. Klastrowanie jest operacją jednorazową. Klastrujemy tabelę według wskazanego indeksu. Musisz pamiętać, że nowe dane dochodzące do tabeli po klastrowaniu nie będą uporządkowane w ten sam sposób. To wymusza okresowe odtwarzanie klastrowania gdybyś zechciał uporządkować nowe wiersze. Ważna uwaga – podczas klastrowania na tabeli zakładana jest blokada wyłączna co skutkuje całkowitym zablokowaniem dostępu do niej – z odczytem włącznie na czas operacji.

Jeśli zazwyczaj odczytujesz wiersze z tabeli w sposób sekwencyjny, klastrowanie Ci nie pomoże. Odczujesz korzyść z klastrowania wyłącznie jeśli wybierasz je według jakiejś wartości w kolumnie na której założony jest indeks o który oparte jest klastrowanie. Kolejna ważna uwaga. Dokumentacja głosi, że na czas skanowania indeksu o który oparty jest klaster tworzona jest tymczasowa tabela zawierająca dane z tabeli uporządkowane wg sortowania w indeksie. Tworzone są również kopie innych indeksów leżących na tej tabeli. To oznacza, że musimy dysponować wolną przestrzenią o wielkości co najmniej takiej jak tabela i indeksy na niej razem.

Najlepiej będzie przetestować efektywność tego rozwiązania na przykładzie. Ponownie skorzystamy z naszej przykładowej tabeli „zlecenia”. Sprawdzam ilość wartości występujących w kolumnie budżet. Mamy 100 różnych wartości na ponad 2 miliony wierszy. Zróżnicowanie nie jest więc zbyt duże.




Sprawdźmy więc jak przedstawia się czas wybrania zleceń o budżetach 20 i 30 z tabeli. Na razie nie mam żadnych indeksów, ani tabela nie jest klastrowana:


explain (analyze,buffers) select * from zlecenia where budzet in (20,30);




Zakładam indeks na kolumnę budżet. Zobaczmy o ile spadnie koszt zapytania:


create index pod_klaster on zlecenia(budzet);

explain (analyze,buffers) select * from zlecenia where budzet in (20,30);




Koszt spadł niemal trzykrotnie. Selektywność jest na poziomie 2%. Gdyby wiersze z taką samą wartością w kolumnie budżet leżały obok siebie w tabeli, na pewno ich odczytanie byłoby znacznie szybsze.


Klastruję tabelę wg nowo stworzonego indeksu:


cluster zlecenia using pod_klaster;

explain (analyze,buffers) select * from zlecenia where budzet in (20,30);




Trochę to potrwało, ale i opłacało się. Czas wykonania w sumie spadł z ok 150 tys do 461...

Tabela może być sklastowana tylko wg jednego kryterium. Nie możemy założyć kilku indeksów i sklastrować tabeli wg każdego z nich. Wybieramy więc taką kolumnę, po której filtrowanie koszuje najwięcej.

Pamiętaj że dane zostały dobrze poukładane na ten moment, nowo wstawiane zlecenia będą już leżały w innym miejscu tabeli. Dobrze jest więc raz na jakiś czas odświeżyć klastrowanie. Jeśli już raz przeprowadziłeś tę operację dla wybranej tabeli możesz wywołać taką komendę:


cluster zlecenia;


Lub ponowić operację dla wszystkich klastrowanych tabel w bazie:


cluster;



Ten artykuł jest elementem poniższych kursów: