12.9. Предпочтительные типы индексов для текстового поиска#

12.9. Предпочтительные типы индексов для текстового поиска

12.9. Предпочтительные типы индексов для текстового поиска

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

Для создания такого индекса выполните одно из следующих действий:

CREATE INDEX name ON table USING GIN (column);

Создает индекс на основе GIN (Generalized Inverted Index). Столбец column должен иметь тип tsvector.

CREATE INDEX name ON table USING GIST (column [ { DEFAULT | tsvector_ops } (siglen = number) ] );

Создает индекс на основе GiST (Generalized Search Tree).column может быть типа tsvector или tsquery. Необязательный целочисленный параметр siglen определяет длину сигнатуры в байтах (см. ниже для получения более подробной информации).

GIN индексы являются предпочтительным типом индекса полнотекстового поиска. Как инвертированные индексы, они содержат запись индекса для каждого слова (лексемы) с сжатым списком совпадающих местоположений. Поиск по нескольким словам может найти первое совпадение, а затем использовать индекс для удаления строк, которым не хватает дополнительных слов. GIN индексы хранят только слова (лексемы) значений tsvector, а не их весовые метки. Таким образом, требуется повторная проверка строки таблицы при использовании запроса, который включает веса.

Индекс GiST является потерянным, что означает, что индекс может давать ложные совпадения, и необходимо проверять фактическую строку таблицы, чтобы исключить такие ложные совпадения. (Tantor SE делает это автоматически при необходимости). Индексы GiST являются потерянными, потому что каждый документ представлен в индексе фиксированной длиной подписи. Длина подписи в байтах определяется значением необязательного целочисленного параметра siglen. По умолчанию длина подписи (когда siglen не указан) составляет 124 байта, максимальная длина подписи составляет 2024 байта. Подпись генерируется путем хеширования каждого слова в один бит в строке из n бит, с помощью операции ИЛИ всех этих битов для получения подписи документа из n битов. Когда два слова хешируются в одну и ту же позицию бита, возникает ложное совпадение. Если все слова в запросе имеют совпадения (реальные или ложные), то строка таблицы должна быть извлечена, чтобы увидеть, является ли совпадение правильным. Более длинные подписи обеспечивают более точный поиск (сканирование меньшей доли индекса и меньшее количество страниц кучи), но требуют большего объема индекса.

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

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

Обратите внимание, что время создания индекса GIN часто можно улучшить, увеличив maintenance_work_mem, в то время как время создания индекса GiST не зависит от этого параметра.

Разделение больших коллекций и правильное использование индексов GIN и GiST позволяют реализовать очень быстрые поиски с онлайн-обновлением. Разделение может быть выполнено на уровне базы данных с использованием наследования таблиц, или путем распределения документов по серверам и сбора внешних результатов поиска, например, через доступ к внешним данным (Foreign Data). Последнее возможно, потому что функции ранжирования используют только локальную информацию.