Когда у строки много индексируемых значений (массив тегов, документ, текст), нужен обратный взгляд: «элемент → строки, где он встречается».
Структура
Два уровня: entry tree (B-tree уникальных ключей) и posting lists (отсортированные ctid под каждым ключом). Большой posting list становится posting tree.
рейс → [r1,r7,r9] багаж → [r2,r7,r9]
Запрос по нескольким ключам - пересечение posting lists.
Полнотекст: где B-tree бессилен
LIKE '%x%' (подстрока без известного начала) B-tree не ускоряет -
только Seq Scan. GIN по tsvector с оператором @@ решает:
CREATE INDEX ON docs USING gin (to_tsvector('simple', body));JSONB
CREATE INDEX ON doc USING gin (body); -- @>, ?, ?|
CREATE INDEX ON doc USING gin (body jsonb_path_ops); -- компактнее, в основном @>
Выбор opclass - универсальность против размера (см. operator-classes).
fastupdate и цена записи
Новые записи копятся в pending list и переносятся пачкой при VACUUM (fastupdate) - быстрые вставки ценой просмотра pending list при поиске. GIN дорог на запись (строка со многими элементами = много записей индекса), поэтому уместен там, где читают чаще, чем пишут. Для массивов
- операторы
@>,<@,&&. Геометрия - в gist-spgist.