- PVSM.RU - https://www.pvsm.ru -

Что нового в PostgreSQL 11: INCLUDE-индексы

image

Релиз PostgreSQL 11 состоится еще не скоро, только в октябре. Но фичфриз уже наступил, а значит мы знаем, какие фичи попали в этот релиз, и можем их потестировать, собрав PostgreSQL [1] из ветки master. Особого внимания заслуживает фича под названием INCLUDE-индексы. Патч [2] изначально написан Анастасией Лубенниковой [3], а потом допилен Александром Коротковым [4] и Федором Сигаевым [5]. Протолкнуть его в PostgreSQL заняло «всего лишь» что-то около трех лет.

Давайте попробуем разобраться, что же это за индексы за такие. Для начала создадим табличку для опытов:

create table test (k serial primary key, v text, ts timestamp);
insert into test (v, ts) select 'key_' || s , now() from generate_series(1, 10000) as s;

… и построим по ней обычный btree-индекс:

create index on test (v);

Взглянем на план выполнения следующего запроса:

=# explain select v, ts from test where v > 'key_1337' and v < 'key_2337';
                                 QUERY PLAN                                  
-----------------------------------------------------------------------------
 Bitmap Heap Scan on test  (cost=31.57..112.09 rows=1101 width=16)
   Recheck Cond: ((v > 'key_1337'::text) AND (v < 'key_2337'::text))
   ->  Bitmap Index Scan on test_v_idx  (cost=0.00..31.29 rows=1101 width=0)
         Index Cond: ((v > 'key_1337'::text) AND (v < 'key_2337'::text))
(4 rows)

Смотрите, что происходит. Поскольку индекс построен по колонке v, а в запросе мы выбираем v и ts, PostgreSQL вынужден выполнять запрос в два шага. Сначала он идет по индексу и находит строки, удовлетворяющие условию. Затем ему приходится сходить в таблицу для получения ts.

Идея INCLUDE-индексов заключается в том, чтобы включить все необходимые для выполнения запроса данные прямо в индекс (но не индексировать их). Таким образом, запрос становится возможно выполнить за один index scan.

Давайте проверим:

drop index test_v_idx;
create index on test (v) include (ts);
explain select v, ts from test where v > 'key_1337' and v < 'key_2337';

Результат:

 Index Only Scan using test_v_ts_idx on test  (cost=0.29..46.30 rows=1101 width=16)
   Index Cond: ((v > 'key_1337'::text) AND (v < 'key_2337'::text))
(2 rows)

За счет того, что теперь мы не ходим в таблицу, запрос должен работать быстрее. Стоит однако отметить, что на практике все зависит от ваших данных. Каждый случай уникален, поэтому я сознательно не привожу здесь каких-то синтетических бенчмарков [6]. Может оказаться, что на ваших объемах данных index only scan с include-индексами работает так же быстро, как и в случае с обычными индексами. А то и вовсе накопленная статистика говорит PostgreSQL, что запрос быстрее сделать heap scan'ом. Такое может произойти, например, если селективность вашего запроса низка.

Так или иначе, знать про эту возможность полезно, и я искренне рад, что она появится в PostgreSQL 11.

Автор: Aleksander Alekseev

Источник [7]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/postgresql/277354

Ссылки в тексте:

[1] собрав PostgreSQL: https://eax.me/postgresql-build/

[2] Патч: https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=8224de4f42ccf98e08db07b43d52fed72f962ebb

[3] Анастасией Лубенниковой: https://habrahabr.ru/users/lubennikovaav/

[4] Александром Коротковым: https://habrahabr.ru/users/smagen/

[5] Федором Сигаевым: http://sigaev.ru/

[6] синтетических бенчмарков: https://eax.me/benchmarks/

[7] Источник: https://habrahabr.ru/post/353126/?utm_source=habrahabr&utm_medium=rss&utm_campaign=353126