Sortowanie przyrostowe w PostgreSQL 13

Jedną z nowych technik optymalizacji wydajności, jakie pojawiły się w PostgreSQL 13 jest sortowanie przyrostowe (incremental sorting). Znajduje ono zastosowanie w zapytaniach, które sortują rekordy według klucza wielokolumnowego. W przeszłości, popularnym sposobem na optymalizację takich sortowań było utworzenie indeksu na wszystkich kolumnach klucza sortowania. Obecnie, serwer PostgreSQL potrafi w takiej sytuacji skorzystać również z indeksu obejmującego tylko część (początkową) kolumn klucza sortowania, a następnie „dosortować” rekordy według końcowych kolumn klucza. Dzięki temu mechanizmowi, PostgreSQL 13 niewątpliwie częściej będzie wykorzystywać indeksy do optymalizacji sortowań, co przełoży się na ogólną poprawę wydajności.

Przedstawmy działanie i efekty wydajnościowe sortowania przyrostowego w PostgreSQL 13. Utworzymy w tym celu trzykolumnową tabelę, zawierającą 10 000 rekordów, a następnie przeanalizujemy plan wykonania zapytania, które sortuje rekordy według dwukolumnowego klucza:

create table demo as 
select random()*1000 as x, random()*1000 as y, random()*1000 as z
from generate_series(1,10000);

explain analyze select z from demo order by x,y limit 1;

                          QUERY PLAN 
-----------------------------------------------------------------
Limit  (cost=214.00..214.00 rows=1 width=24) 
   ->  Sort  (cost=214.00..239.00 rows=10000 width=24) 
         Sort Key: x, y
         Sort Method: top-N heapsort  Memory: 25kB
         ->  Seq Scan on demo  (cost=0.00..164.00 rows=10000) 
Planning Time: 0.131 ms
Execution Time: 3.031 ms

Jak widać, algorytm Quicksort wykonał w pamięci operacyjnej pełne sortowanie rekordów według x,y.

Utwórzmy teraz indeks jedynie na pierwszej kolumnie wykorzystywanej w kluczu sortowania i ponownie przeanalizujmy plan wykonania wcześniejszego zapytania:

create index i_x on demo(x);

explain analyze select z from demo order by x,y limit 1;

                  QUERY PLAN
-----------------------------------------------------------------
Limit  (cost=0.35..0.45 rows=1 width=24)
   ->  Incremental Sort  (cost=0.35..976.27 rows=10000 width=24)
         Sort Key: x, y
         Presorted Key: x
         Full-sort Groups: 1  Sort Method: quicksort  Average Memory: 25kB  Peak Memory: 25kB
         ->  Index Scan using i_x on demo  (cost=0.29..526.27 rows=10000 width=24)
Planning Time: 0.360 ms
Execution Time: 0.077 ms

Zaobserwowaliśmy właśnie użycie sortowania przyrostowego przez PostgreSQL (operacja „Incremental Sort”). Z opisu planu wykonania wynika, że w pierwszej kolejności, indeks i_x posłużył do wstępnego posortowania rekordów według kolumny x, a w drugiej kolejności, w ramach grup rekordów o identycznych wartościach x, nastąpiło „dosortowanie” według kolumny y. PostgreSQL 12 w tej sytuacji nie potrafił zastosować takiego „cząstkowego” indeksu.

Oczywiście, na osiągnięcie jeszcze lepszego rezultatu pozwoliłby indeks utworzony na obu kolumnach klucza sortowania:

create index i_xy on demo(x,y);

explain analyze select z from demo order by x,y limit 1;

    QUERY PLAN                                             
-----------------------------------------------------------------
Limit  (cost=0.29..0.34 rows=1 width=24)
   ->  Index Scan using i_xy on demo  (cost=0.29..570.28 rows=10000 width=24) 
Planning Time: 0.359 ms
Execution Time: 0.060 ms

tyle tylko, że nie zawsze takim indeksem dysponujemy, a skok wydajnościowy nie jest już tak bardzo zauważalny.

Przy okazji wprowadzenia nowej metody sortowania pojawił się też parametr konfiguracyjny, który pozwala ją aktywować/dezaktywować: enable_incremental_sort. Dobrej zabawy!

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *