Qdrant - Vector Database

Payload Индексы

1 млн документов. Семантический поиск работает за 5ms. Но добавить фильтр 'только published articles за 2024 год' - и запрос занимает 300ms. Причина: full scan по payload. Один createPayloadIndex - и снова 5ms.

  • **E-commerce:** фильтры по категории + ценовому диапазону + наличию - все три поля должны быть проиндексированы
  • **Новостной агрегатор:** фильтрация по дате публикации (datetime) + языку (keyword) + теме (keyword) - стандартный набор
  • **Геосервис:** поиск похожих мест в радиусе 5 км - geo-индекс обязателен

Предварительные знания

  • Points, Vectors, Payloads

Зачем нужны payload-индексы

**Payload-индекс** - структура данных, позволяющая Qdrant быстро фильтровать точки по значениям payload-полей. Без индекса каждый фильтрующий запрос требует **full scan** - перебора всех точек коллекции.

**Когда создавать индексы:** для любого поля, задействованного в регулярных фильтрах. Qdrant создаёт индексы явно через API - это позволяет не индексировать поля, которые используются редко.

**Индексы не блокируют запросы.** При создании индекса на заполненной коллекции Qdrant строит его в фоне. До окончания построения фильтры работают через full scan (медленно), после - через индекс (быстро). Прогресс можно отслеживать через `/collections/{name}` API.

Коллекция 500k точек. Фильтр по полю 'status' (значения: 'active', 'archived') используется в 80% запросов. Индекса нет. Какой эффект?

Типы индексов: keyword, integer, float, geo, text, datetime

**Qdrant поддерживает 6 типов payload-индексов**, каждый оптимизирован под свой тип данных и паттерн запросов.

Тип индексаТип данныхПоддерживаемые фильтрыПримеры полей
keywordstringmatch, is_null, is_emptycategory, status, language, tag
integerint64match, range (gte/lte/gt/lt)year, user_id, view_count, priority
floatfloat64range (gte/lte/gt/lt)price, score, latitude, longitude
geo{ lon, lat }geo_bounding_box, geo_radius, geo_polygonlocation, coordinates
textstring (full-text)match.text (full-text search)description, content, title
datetimeRFC3339 stringrange (gte/lte/gt/lt)created_at, published_at, expires_at

Нужно искать рестораны: по кухне (семантически, через вектор), в радиусе 3 км, с рейтингом >= 4.5, открытые в данный момент (поле is_open = true). Какие индексы создать?

Создание индексов: практический пример

**Полный workflow:** создание коллекции, добавление точек, создание индексов, фильтрующий поиск. Индексы создаются после добавления данных - Qdrant строит их в фоне.

**Индексируйте только нужные поля.** Каждый индекс занимает дополнительную память (~50-200MB на 1M точек) и замедляет запись новых точек. Хорошее правило: индексируйте поля, используемые в фильтрах в >20% запросов. Редкие фильтры - пусть делают full scan.

Создавать индексы на все payload-поля «на всякий случай»

Индексировать только поля из фильтров. Избыточные индексы: +память, -скорость записи, нулевая польза от поиска

Каждый индекс нужно поддерживать при каждой записи новой точки (upsert). На 20 индексах вместо 5 - upsert в 4 раза медленнее. Плюс каждый индекс занимает RAM. Правило: индекс только если поле в фильтрах

Добавлен 1 млн точек, затем создан индекс на 'category'. В этот момент поступает запрос с фильтром по category. Что произойдёт?

Ключевые идеи

  • **Без индекса = full scan:** каждый фильтр перебирает все точки O(N). С индексом - O(log N)
  • **6 типов:** keyword (категории), integer/float (числа/диапазоны), geo (геолокация), text (full-text), datetime (время)
  • **createPayloadIndex** создаётся после данных, работает онлайн - не блокирует запросы
  • **Индексируйте умеренно:** только поля в фильтрах. Каждый лишний индекс = память + медленнее запись
  • **Проверить индексы:** `getCollection` → `payload_schema`

Что дальше

Payload-индексы ускоряют фильтрацию. Следующий шаг - sparse vectors для лексического поиска, который работает совместно с семантическим.

  • Sparse Vectors: BM42 и SPLADE — Лексический поиск дополняет семантический - вместе это Hybrid Search
  • Квантизация векторов — Сжатие памяти - важно когда много индексов занимают RAM
  • HNSW: Как работает индекс — HNSW + payload-индексы работают вместе для filtered vector search

Вопросы для размышления

  • Как Qdrant решает: использовать payload-индекс или HNSW-первым при filtered vector search? Что происходит когда фильтр очень селективный?
  • В коллекции хранится JSON с вложенными объектами (article.author.country). Как создать индекс на вложенное поле?
  • Если 95% ваших запросов используют фильтр по 'is_active: true', но только 10% точек активны - стоит ли создавать keyword-индекс?

Связанные уроки

  • db-09-indexes-btree
Payload Индексы

0

1

Войти