К содержимому страницы

Векторный поиск в продакшене: pgvector против Qdrant и Weaviate

За последний год векторный поиск перестал быть экзотикой. Поисковая выдача, рекомендации, RAG-сценарии для LLM, semantic-кэш для AI-агентов — всё это требует хранилища, в котором можно быстро искать «похожее» по косинусу или скалярному произведению. Мы прошли через три варианта в реальных проектах и поделимся компромиссами.

pgvector: когда хватает Postgres

Расширение pgvector превращает обычный Postgres в вполне рабочее векторное хранилище. Главный плюс — данные и индекс лежат там же, где остальной транзакционный набор. Не нужно синхронизировать две базы и разруливать рассогласование при сбоях. JOIN с продуктами, фильтрация по tenant_id, классические индексы по дате — всё работает.

Узкое место — производительность HNSW-индекса под высокой записью. Каждый INSERT перестраивает соседей в графе. На ~5М векторов и потоке 500 w/s мы упирались в CPU мастера. Решение: batch-вставка раз в минуту через staging-таблицу, либо переход на ivfflat-индекс — он медленнее на поиске, но дешевле на записи.

Qdrant: когда нужен миллиард векторов

Qdrant написан на Rust, шардируется горизонтально и умеет хранить вектор + метаданные с типизированной фильтрацией. На объёмах 50М+ векторов и сложных фильтрах (категория, регион, цена) он стабильно обгоняет pgvector в 5–10 раз по p99. Поддерживает гибридный поиск (плотный + разрежённый).

Минусы: вторая операционная сущность, отдельные снапшоты, отдельный мониторинг, отдельная политика бэкапов. Если основная база — Postgres, нужна аккуратная архитектура «источник истины → event bus → Qdrant». Без этого получите рассинхрон через несколько недель.

Weaviate: когда поиск — часть продукта

Weaviate ближе к «базе для AI», чем просто хранилищу векторов. Из коробки — модули генерации эмбеддингов, классификация, мультимодальный поиск (текст + картинка). Удобно, если команда не хочет содержать отдельный embedding-сервис.

Цена удобства — выше overhead и менее предсказуемые латентности под нагрузкой. На двух проектах мы в итоге выносили embedding наружу и использовали Weaviate как чистое хранилище — что нивелирует основное преимущество перед Qdrant.

Как выбираем

В каждом случае мы закладываем «миграционный путь»: pgvector → Qdrant через event-лог проще, чем кажется, если эмбеддинги хранятся в Postgres рядом с первоисточником.