Перейти к основному содержимому

btree_gist. Показательные классы операторов GIST

В исходном дистрибутиве установлено по умолчанию: нет.

Связанные компоненты: отсутствуют

Схема размещения: ext

Модуль предоставляет показательные классы операторов GiST, которые реализуют поведение, подобное поведению обычных классов B-дерева (b-tree), для следующих типов данных:

  • int2;
  • int4;
  • int8;
  • float4;
  • float8;
  • timestamp with time zone;
  • timestamp without time zone;
  • time with time zone;
  • time without time zone;
  • date;
  • interval;
  • oid;
  • money;
  • char;
  • varchar;
  • text;
  • bytea;
  • bit;
  • varbit;
  • macaddr;
  • macaddr8;
  • inet;
  • cidr;
  • uuid;
  • все типы enum.

Описание

Работа с индексами GiST

GiST (Generalized search tree) - сбалансированное дерево поиска, схожее с b-tree. Однако, в отличие от b-tree, которое поддерживает только операторы <, >, =, GiST дает возможность использовать самые разнообразные операторы, например (<@, &&). При этом смысл операторов определяется типом данных, для которого он применяется. Таким образом, GiST предоставляет расширяемый интерфейс для хранения и поиска по любым типам данных с использованием операций, специфичных именно для этого типа.

Рассмотрим в качестве примера задачу поиска по временным интервалам (тип tsrange). Допустим, сдается дом, и есть таблица, хранящая интервалы бронирования:

CREATE TABLE reservations(during tsrange);
INSERT INTO reservations(during) VALUES
('[2016-12-30, 2017-01-09)'),
('[2017-02-23, 2017-02-27)'),
('[2017-04-29, 2017-05-02)');
CREATE INDEX ON reservations USING gist(during);

На вход подается интервал [2017-01-01, 2017-04-01), нужно найти все интервалы, пересекающиеся с ним:

SELECT * FROM reservations WHERE during && '[2017-01-01, 2017-04-01)';

Для типа tsrange оператор && означает «пересечение».

Индекс GiST может применяться для поддержки ограничений исключения (exclude).

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

ALTER TABLE reservations ADD exclude USING gist(during WITH &&);

Попытка добавить интервал, уже имеющийся в таблице, завершится ошибкой:

INSERT INTO reservations(during) VALUES ('[2017-01-01, 2017-04-01)');

Описание расширения btree_gist

Допустим, нужно сдавать несколько домов. В таблицу reservation добавьте номер дома:

ALTER TABLE reservations ADD house_no INTEGER DEFAULT 1;

Необходимо изменить ограничение исключения так, чтобы учитывать и номер дома. Однако GiST не поддерживает операцию равенства для целых чисел.

В этом случае используйте расширение btree_gist, которое добавляет GiST-поддержку операций, характерных для B-деревьев (<, >, =):

CREATE extension btree_gist;
ALTER TABLE reservations DROP CONSTRAINT reservations_during_excl;
ALTER TABLE reservations ADD exclude USING gist(during WITH &&, house_no WITH =);

Убедитесь, что можно забронировать на те же даты не только первый дом, но и второй

INSERT INTO reservations(during, house_no) VALUES ('[2017-01-01, 2017-04-01)', 2);

Учитывайте, что при необходимости простого сравнения (<, >, =), более предпочтительно использовать простые b-tree индексы, так как они работают быстрее.

btree_gin имеет смысл использовать только в том случае, если условие дополнительно содержит операцию над сложными объектами, как в примере выше.

В дополнение к основным операциям b-tree, btree_gin добавляет оператор <> (не равно), который удобно использовать в ограничениях исключения (exclude constraints). Например:

CREATE TABLE zoo ( cage INTEGER, animal TEXT, EXCLUDE USING gist (cage WITH =, animal WITH <>) );

Доработка

Не проводилась.

Ограничения

Существуют следующие ограничения:

  • классы операторов GiST не будут работать быстрее аналогичных стандартных методов индекса-B-tree;
  • нет возможности ограничивать уникальность.

Установка

Расширение входит в стандартную поставку Pangolin. Для использования необходимо выполнить:

CREATE EXTENSION btree_gist SCHEMA ext;

Настройка

Не требуется.

Использование модуля

Использование btree_gist вместо btree:

CREATE TABLE test (a int4);
-- создать индекс
CREATE INDEX testidx ON test USING GIST (a);
-- запрос
SELECT * FROM test WHERE a < 10;
-- поиск ближайших соседей: найти десять записей, ближайших к "42"
SELECT *, a <-> 42 AS dist FROM test ORDER BY a <-> 42 LIMIT 10;

Ссылки на документацию разработчика

Дополнительно поставляемый модуль btree_gist: https://www.postgresql.org/docs/15/btree-gist.html.