GIN и GiST

Тема дорожной карты · PostgreSQL

GIN (Generalized Inverted Index, обобщённый инвертированный индекс) и GiST (Generalized Search Tree, обобщённое дерево поиска) — расширяемые типы индексов PostgreSQL, предназначенные для сложных структур данных, которые нельзя эффективно обработать стандартным индексом B-tree. GIN-индексы оптимизированы для многозначных данных — документов JSONB, столбцов ARRAY и значений tsvector полнотекстового поиска: команда CREATE INDEX ON documents USING GIN (body_tsv) обеспечивает быстрые запросы на вхождение с операторами @>, ?, @@ и && по миллионам строк в реляционной базе данных PostgreSQL. GiST-индексы поддерживают геометрические типы и диапазоны, позволяя выполнять поиск по близости, запросы по ограничивающему прямоугольнику и поиск ближайших соседей через оператор расстояния <->, что делает их основой пространственного индексирования PostGIS. Оба типа — GIN и GiST — являются центральными элементами расширяемости PostgreSQL: они используются в качестве бэкенда индексирования такими расширениями, как pg_trgm (поиск по триграммному сходству), earthdistance и btree_gin, расширяющими возможности оптимизации запросов далеко за пределы возможностей типичных реляционных СУБД.

Как это работает

GIN и GiST ускоряют чтение ценой записи + storage. Типы Postgres: B-tree (дефолт, равенство + диапазон), Hash (только равенство), GIN (full-text, JSONB, containment массивов), GiST (геометрия, full-text), BRIN (огромные таблицы с естественным порядком — time-series), Bloom (multi-column равенство). Partial indexes (WHERE) пропускают нерелевантные строки; expression indexes ((lower(email))) ловят запрос с трансформацией; covering indexes (INCLUDE) избегают heap-lookup (index-only scans).

Когда применять

Индексируйте колонки в WHERE / JOIN / ORDER BY для запросов, которые реально гоняете — никогда "на всякий случай". EXPLAIN (ANALYZE, BUFFERS) — подтвердить, что индекс используется. Для JSONB-запроса по ключу — GIN на поле; для full-text — to_tsvector + GIN. BRIN — для append-only данных с монотонными timestamp: крошечный индекс, огромные таблицы. Удаляйте неиспользуемые индексы (pg_stat_user_indexes: idx_scan = 0).

Типичные ошибки

Ловушки GIN и GiST: слишком много индексов (каждый INSERT/UPDATE переписывает их все — write amplification); функциональные WHERE (WHERE lower(email) = ?) без соответствующего expression-index (full-scan); B-tree на boolean (низкая cardinality, бесполезно — partial index WHERE flag = true правильно); не CREATE INDEX CONCURRENTLY в production (обычный CREATE INDEX лочит записи). Всегда ANALYZE после больших записей — статистика планировщика свежая.

Связанные понятия

Полезные ресурсы