PostgreSQL 13 – szczęśliwa liczba w świecie Postgresa
Wielu ludzi cierpi na irracjonalny lęk przed liczbą 13, co fachowo określa się mianem triskaidekafobii. W przypadku szykującego się najnowszego wydania PostgreSQL, opatrzonego właśnie tą liczbą, obawy są jednak bezzasadne. Niemal każdy będzie mógł w nim znaleźć zmiany poprawiające wykorzystywane na co dzień aspekty Postgresa.
Wielu ludzi cierpi na irracjonalny lęk przed liczbą 13, co fachowo określa się mianem triskaidekafobii. W przypadku najnowszego wydania PostgreSQL, opatrzonego właśnie tą liczbą, obawy są jednak bezzasadne. Niemal każdy znajdzie w nim zmiany poprawiające wykorzystywane na co dzień aspekty Postgresa.
Spróbujmy więc „odczarować” pozorną pechowość 13. wydania PostgreSQL. Pierwszą rzucającą się w oczy sprawą jest ogrom pracy włożony w to wydanie. Nie ma chyba podsystemów, na których polega wiele produkcyjnych wdrożeń, których to wydanie w jakiś sposób by nie dopieszczało.
Kilka ostatnich głównych wydań to duże zmiany w świecie PostgreSQL. Każde z nich przyniosło ogrom zmian i nowych funkcji jak na przykład partycjonowanie, natywna replikacja logiczna czy wsparcie dla typu JSON. W przypadku tego wydania sprawy mają się jednak inaczej i otrzymamy w nim poprawki dla już istniejących funkcji. Co nie znaczy, że nie mamy się czym ekscytować!
Mniejsze indeksy
Pierwszym ulepszeniem, które zdecydowanie przyda się wszystkim użytkownikom Postgresa, jest zmiana w wielkości standardowych indeksów opartych o B-drzewa (B-tree). Ten typ indeksu jest najczęściej wykorzystywany, ponieważ to właśnie on zostanie utworzony po wykonaniu polecenia CREATE INDEX
. Zmniejszenie jego rozmiaru zdecydowanie cieszy, szczególnie że wraz z mniejszym rozmiarem można również spodziewać się szybszego dostępu do przechowywanych w nim informacji. Poprawka w wielkości indeksów głównie odnosi się do zmian w wykrywaniu zduplikowanych wartości (można o tym poczytać w dokumentacji implementacji B-drzew w Postgresie).
Jak to wygląda w praktyce? Korzystając z poniższego dość „zabawkowego” przykładu, możemy pokazać, jak zmiana pomiędzy głównymi wersjami może mieć wpływ na zajętość produkcyjnych dysków.
--- Przykładowa tablica CREATE TABLE index_test(id int PRIMARY KEY, value int); CREATE INDEX ON index_test (value); --- Dodanie danych do tablicy INSERT INTO index_test SELECT i, i % 12345 FROM generate_series(1,1000000) i;
W przypadku wersji 12 wielkość indeksu, w którym znajdują się zduplikowane dane, prezentuje się następująco:
--- Wynik dla wersji 12 postgres=# select pg_size_pretty(pg_relation_size('index_test_pkey')); pg_size_pretty ---------------- 21 MB (1 row)
Natomiast dla wersji 13 widzimy blisko 60%-ową redukcję rozmiaru:
postgres=# select pg_size_pretty(pg_relation_size('index_test_value_idx')); pg_size_pretty ---------------- 8664 kB (1 row)
Jak wygląda porównanie wydajności? Od razu warto zaznaczyć, że tworzenie poprawnych testów tego typu to nietrywialne zadanie. Wydajność zależy od ogromnej ilości czynników, o niekoniecznie ortogonalnych czy nawet linearnych relacjach. Poniżej podajemy więc nasze wyniki, raczej jako anecdata niż twarde dane ;)
Skorzystaliśmy z poniższego zapytania:
EXPLAIN ANALYZE SELECT count(*) FROM index_test WHERE value = 42;
Poniżej plan zapytania dla wersji 12:
QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------- Aggregate (cost=297.39..297.40 rows=1 width=8) (actual time=0.433..0.434 rows=1 loops=1) -> Bitmap Heap Scan on index_test (cost=5.05..297.19 rows=81 width=0) (actual time=0.118..0.394 rows=81 loops=1) Recheck Cond: (value = 42) Heap Blocks: exact=81 -> Bitmap Index Scan on index_test_value_idx (cost=0.00..5.03 rows=81 width=0) (actual time=0.036..0.036 rows=81 loops=1) Index Cond: (value = 42) Planning Time: 0.490 ms Execution Time: 0.509 ms
Oraz dla wersji 13:
QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------- ------ Aggregate (cost=6.04..6.05 rows=1 width=8) (actual time=0.059..0.060 rows=1 loops=1) -> Index Only Scan using index_test_value_idx on index_test (cost=0.42..5.84 rows=81 width=0) (actual time=0.046..0.052 rows=81 loops=1) Index Cond: (value = 42) Heap Fetches: 0 Planning Time: 0.237 ms Execution Time: 0.082 ms
Jak widać, nawet tak podstawowe elementy bazy danych jak indeksy mogą wiele zyskać przy wprowadzeniu odpowiednich poprawek przez społeczność Open Source. W przypadku upgrade’u z poprzednich wersji, aby skorzystać z tej zmiany, trzeba będzie dokonać przebudowania indeksu. Na szczęście poprzednie 12 wydanie PostgreSQL dodało możliwość skorzystania z opcji REINDEX CONCURRENTLY
. Nie trzeba więc przygotowywać okna serwisowego przez blokującą opcję REINDEX
.
Nowe parametry ułatwiające monitorowanie
Monitorowanie działania bazy danych to jedna z podstawowych czynności administracyjnych. Jednym z nieprzebranych wręcz źródeł informacji są logi systemowe pozwalające na określenie stanu zdrowia bazy danych i wskazujące, gdzie kierować swoją uwagę w celu poprawienia jej wydajności. Jednym z narzędzi do analizy logów jest moduł LogAnalyzer.
Aby najlepiej wykorzystać możliwości analizatora, należałoby zapisywać wszystkie zdarzenia w bazie danych. Nie jest to oczywiście możliwe w praktyce dla systemów produkcyjnych, ponieważ najwyższy poziom szczegółowości jest bardzo obciążający i powoduje obniżenie wydajności. Do czasu wersji 12 administratorzy mieli do wykorzystania parametr log_min_duration_statement
powodujący zapisanie zapytania w logu, jeśli czas jego wykonania był dłuższy niż wartość graniczna. Pomagało to zidentyfikować pojedyncze długie zapytania. Jednak w dość oczywisty sposób powodowało skupianie się jedynie na wycinku rzeczywistości, nie dając poglądu na system bazodanowy jako całość.
W wersji 12 pojawił się parametr log_transaction_sample_rate
, dzięki czemu można określić, jaki procent ze wszystkich zapytań zostanie zapisany w logu. Pozwala to na zmitygowanie problemu obniżenia wydajności, jednocześnie dając ogląd na stan całej bazy danych. PostgreSQL 13 rozwija ten pomysł i pozwala na dokładniejsze sterowanie logowaniem dzięki nowym parametrom konfiguracyjnym. Są to:
log_min_duration_sample
– dodający możliwość logowania wolniejszych zapytań podobnie jaklog_min_duration_statement
log_statement_sample_rate
– kontrolujący próbkowanie dla powyższego parametru.
Dobranie odpowiednich wartości dla każdej aplikacji korzystającej z Postgresa mocno wykracza poza zakres tego artykułu. Warto jednak wspomnieć, że prawdopodobnie jedynie praktyczne testy pozwalają na znalezienia optymalnych ustawień.
Podsumowanie
Gratulujemy twórcom kolejnego dobrego kroku, a użytkowników zachęcamy do aktualizacji. PostgreSQL w wersji 13 został oficjalnie wydany w 24.09.2020 r. Szczegółowe informacje o wydaniu znajdziecie pod linkiem: https://www.postgresql.org/docs/13/release-13.html