Многоколоночный индекс на 3 поля с гетерогенными типами данных

У меня есть таблица postgres с тремя полями:

  • a: геометрия postgis
  • b: массив varchar []
  • c: integer

и у меня есть запрос, который включает в себя все из них. Я бы хотел добавить многоколоночный индекс, чтобы ускорить его, но я не могу, поскольку 3 поля не могут попасть под один и тот же индекс из-за их природы.

Какова стратегия в этом случае? Добавление 3 индексов gist, gin и btree и postgres будет использовать их во время запроса?

Ответ 1

Индекс с одним столбцом

Прежде всего, Postgres может очень эффективно комбинировать несколько индексов в одном запросе с помощью сканирования растровых изображений. В большинстве случаев Postgres выбирает наиболее избирательный индекс (или два и объединяет их с растровыми индексами) и фильтрует остальные после сканирования кучи растровой карты. Как только набор результатов достаточно узкий, он неэффективен для сканирования другого индекса.

Индекс многоколоночных

По-прежнему быстрее иметь идеально подходящий многоколоночный индекс, но не на порядок.
Поскольку вы хотите включить массив типа, я предлагаю использовать индекс GIN. AFAIK, классы операторов отсутствуют для универсальных индексов GiST по типу массива. (Исключение составляет intarray для integer массивов.)

Чтобы включить столбец integer, сначала установите дополнительный модуль btree_gin, который предоставляет необходимые Классы операторов GIN. Выполняется один раз в базе данных:

CREATE EXTENSION btree_gin;

Затем вы сможете создать свой многоколоночный индекс:

CREATE INDEX tbl_abc_gin_idx ON tbl USING GIN(a, b, c);

Порядок индексных столбцов не имеет значения для индексов GIN. В документации:

Многоколоночный индекс GIN может использоваться с условиями запроса, которые включают любое подмножество столбцов индекса. В отличие от B-дерева или GiST, поиск по индексу эффективность одинакова независимо от того, какой индексный столбец (столбцы) условия запроса.

Поиск ближайшего соседа

Поскольку вы включаете тип PostGis geometry, скорее всего, вы хотите сделать поиск ближайшего соседа, для которого вам понадобится GiST. В этом случае я предлагаю два индекса:

CREATE INDEX tbl_ac_gist_idx ON tbl USING GiST(a, c);  -- geometry type
CREATE INDEX tbl_bc_gin_idx  ON tbl USING GIN(b, c);

Вы можете добавить столбец integer c в один или оба. Это зависит. Для этого вам нужно btree_gin или btree_gist или обоих соответственно.

Ответ 2

3 поля не могут проходить под одним и тем же индексом из-за их природы

Oh да, они могут.