Индекс

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

Индекс внутри абзаца существует независимо, но параметры самого индекса настраиваются для всего набора.

Не все абзацы автоматически имеют индексы. Это зависит от требований настроек оптимизации и обычно зависит от количества сохраненных точек.

Индекс нагрузки

Индекс нагрузки в Qdrant похож на индекс в традиционной ориентированной на документы базе данных. Этот индекс строится для конкретных полей и типов, используется для быстрого извлечения точек на основе соответствующих условий фильтра.

Он также используется для точной оценки мощности условий фильтра, что помогает планировщику запросов выбирать стратегии поиска.

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

Для отметки поля как индексируемого можно использовать следующий метод:

PUT /collections/{collection_name}/index
{
    "field_name": "название поля для индексации",
    "field_schema": "keyword"
}

Доступные типы полей:

  • keyword - для ключевых нагрузочных данных, влияющих на соответствующие условия фильтра.
  • integer - для целочисленных нагрузочных данных, влияющих на условия фильтрации и диапазона.
  • float - для нагрузочных данных с плавающей точкой, влияющих на условия диапазона.
  • bool - для булевых нагрузочных данных, влияющих на соответствующие условия фильтрации (доступно с версии 1.4.0 и выше).
  • geo - для географических нагрузочных данных, влияющих на условия географического ограничивающего прямоугольника и радиуса.
  • text - специальный тип индекса, подходящий для ключевых/строковых нагрузочных данных, влияющий на условия фильтрации полнотекстового поиска.

Индексы нагрузки могут потреблять дополнительную память, поэтому рекомендуется индексировать только те поля, которые используются при условиях фильтрации. Если вам необходимо фильтровать по многим полям, и ограничения памяти не позволяют индексировать их всех, рекомендуется выбирать поля, которые наиболее сужают результаты поиска. Как правило, чем больше уникальных значений у нагрузочного значения, тем эффективнее будет использование индекса.

Индекс полнотекстового поиска

Доступен с версии 0.10.0

Qdrant поддерживает полнотекстовый поиск для строковых нагрузочных данных. Индекс полнотекстового поиска позволяет фильтровать точки на основе наличия слов или фраз в поле нагрузки.

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

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

PUT /collections/{collection_name}/index

{
    "field_name": "название поля для индексации",
    "field_schema": {
        "type": "text",
        "tokenizer": "word",
        "min_token_len": 2,
        "max_token_len": 20,
        "lowercase": true
    }
}

Доступные методы токенизации:

  • word - Разделяет строку на основе пробелов, знаков препинания и специальных символов.
  • whitespace - Разделяет строку на основе пробелов.
  • prefix - Разделяет строку на основе пробелов, знаков препинания и специальных символов, а затем создает префиксный индекс для каждого слова. Например, hello будет проиндексировано как h, he, hel, hell, hello.
  • multilingual - Специальный тип токенизации на основе пакета charabia. Он позволяет корректную токенизацию и лемматизацию нескольких языков, включая языки с нелатинскими алфавитами и разделителями, не являющимися пробелами. См. документацию charabia для полного списка поддерживаемых языков и параметров нормализации. По умолчанию в конфигурации сборки qdrant не включена поддержка всех языков, так как это увеличило бы размер двоичных файлов. Китайский, японский и корейский языки по умолчанию отключены, но их можно включить, собрав qdrant из исходного кода с использованием флагов --features multiling-chinese, multiling-japanese, multiling-korean.

Пожалуйста, обратитесь к примерам фильтрации полнотекстового соответствия для получения примера использования индекса полнотекстового поиска для запросов.

Индексирование векторов

Индексирование векторов - это структура данных, основанная на векторах и построенная с использованием конкретных математических моделей. С помощью индексирования векторов мы можем эффективно запрашивать несколько векторов, похожих на целевой вектор.

В настоящее время Qdrant использует только HNSW в качестве векторного индекса.

HNSW (Иерархический Навигируемый Граф Малого Мира) - это алгоритм индексации на основе графа. Согласно определенным правилам, он строит многоуровневую навигационную структуру для графа. В этой структуре верхние слои разрежены, с большими расстояниями между узлами. Нижние слои плотные, с меньшими расстояниями между узлами. Поиск начинается с верхнего слоя, находя ближайший узел к цели в этом слое, а затем происходит вход в следующий слой для еще одного поиска. После нескольких итераций он может быстро приблизиться к целевой позиции.

Для повышения производительности HNSW ограничивает максимальную степень узлов на каждом уровне графа значением m. Кроме того, вы можете указать диапазон поиска с помощью ef_construct (во время построения индекса) или ef (во время поиска цели).

Эти параметры могут быть настроены в конфигурационном файле:

storage:
  hnsw_index:
    m: 16
    ef_construct: 100
    full_scan_threshold: 10000

Во время процесса создания коллекции параметр ef можно настраивать и по умолчанию он равен ef_construct.

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

Доступно с версии v1.1.1

Параметры HNSW также могут быть настроены для коллекций и именованных векторов, чтобы оптимизировать производительность поиска, установив hnsw_config.

Фильтруемый индекс

Отдельные индексы для нагрузки и только для векторов в отдельности не могут полностью решить проблему использования фильтров для поиска.

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

С одной стороны, мы не можем себе позволить выполнять полное сканирование слишком большого числа векторов. С другой стороны, при использовании чрезмерно строгих фильтров граф HNSW начинает разрушаться.

Дополнительные ребра позволяют эффективно использовать индекс HNSW для поиска соседних векторов и применения фильтров во время поиска в графе.

Этот подход минимизирует накладные расходы от проверки условий, поскольку вам нужно вычислять условия только для небольшой части точек, участвующих в поиске.