VK Cloud

Векторные базы данных для RAG: как выбрать движок и поднять Qdrant в VK Cloud

24 августа 2026 г.
шпрингер.png
Елена Шпрингер
Автор статьи
_blog_head_42.png

Векторная база данных нужна там, где полнотекстовый поиск ломается на первом же запросе. Корпоративная база знаний из 50 000 документов, сотрудник спрашивает: «какова политика компании по командировкам». В базе лежат регламент Travel Reimbursement Policy и внутренняя инструкция «возмещение расходов в служебных поездках». Поиск по ключевым словам не вернёт ни того, ни другого: пересечений по словам с запросом нет вообще.

RAG (retrieval-augmented generation) обходит эту проблему подстановкой контекста. Система сначала находит релевантные фрагменты документов, а потом кладёт их в промпт языковой модели вместе с исходным вопросом. Фрагменты находит семантический поиск (semantic search) по эмбеддингам — числовым представлениям смысла текста. Сами векторы хранит и индексирует отдельный класс хранилищ: векторные базы данных.

Выбор векторного хранилища в русскоязычных обзорах обычно сводится к таблице «кто быстрее». Это неверная постановка: у зрелых движков recall (доля нужных документов, попавших в выдачу) на типовых датасетах близок к единице. Решение упирается в объём оперативной памяти, поведение под фильтрами и стоимость переиндексации. Ниже — расчёт памяти под конкретный корпус, критика публичных бенчмарков, сравнение Qdrant, pgvector, Milvus и Weaviate по сценариям и пошаговый запуск Qdrant в VK Cloud.

погоржельский2.jpg

Статья подготовлена вместе с экспертом

Станислав Погоржельский, технологический евангелист VK Cloud&Data

Как работает RAG и зачем нужна векторная база данных

Архитектура RAG: четыре шага

Конвейер RAG распадается на офлайновую индексацию и онлайновый запрос. Индексация проходит один раз на корпус, запрос — на каждый вопрос пользователя. ИНДЕКСАЦИЯ (офлайн, один раз на корпус)

Документы ─► Чанки ─► Embedding-модель ─► Векторы + метаданные ─┐ │ ▼ ┌───────────────────────┐ │ Векторная БД │ │ (векторы + payload │ ЗАПРОС (онлайн, на каждый вопрос) │ + ANN-индекс) │ └───────────────────────┘ Вопрос ─► Тот же эмбеддер ─► Вектор запроса ─► ANN-поиск топ-K ─┘ │ ▼ Найденные чанки + вопрос ─► LLM ─► Ответ

Шаг 1. Документы превращаются в векторы.

Тексты режутся на чанки, каждый чанк проходит через embedding-модель и становится массивом из сотен или тысяч чисел. Рядом с вектором кладётся payload: идентификатор документа, отдел, дата, права доступа.

Шаг 2. Вопрос превращается в вектор тем же эмбеддером.

Разные модели строят несовместимые пространства, поэтому индексировать корпус одной моделью, а запросы кодировать другой нельзя: расстояния потеряют смысл.

Шаг 3. Поиск топ-K ближайших соседей.

На миллионе векторов точный перебор в бюджет латентности не укладывается, поэтому работает приближённый поиск (approximate nearest neighbor, ANN) по заранее построенному индексу.

Шаг 4. Генерация ответа.

Найденные чанки склеиваются с вопросом в промпт и уходят в LLM. Дальше качество ответа определяется тем, попал ли нужный фрагмент в топ-K.

Что хранит векторная БД

Векторная база данных хранит три сущности, и только одна из них дорогая.

  1. Сам вектор — массив float32 размерности от 768 до 4096 в зависимости от эмбеддера: 1536 у OpenAI text-embedding-3-small, 3072 у text-embedding-3-large, 1024 у BGE-M3, 4096 у Qwen3-Embedding-8B. Это основная статья расхода памяти.
  2. Payload (метаданные) — поля, по которым потом идёт фильтрация: отдел, тип документа, дата, ACL. Занимают доли процента от объёма векторов, но определяют, будет ли поиск пригоден для мультитенантного сценария.
  3. ANN-индекс — структура, которая заменяет полный перебор. Для онлайн-поиска это почти всегда граф HNSW (hierarchical navigable small world, многослойный граф ближайших соседей), и он живёт в оперативной памяти.

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

Сколько памяти съест корпус: считаем до выбора движка

Расчёт памяти — самый пропущенный шаг в обзорах векторных БД и первое, что стоит сделать самому. Формула простая:

Размер сырых векторов = число_векторов × размерность × 4 байта (float32)

Оверхед графа HNSW = число_векторов × M × 4 байта

Параметр M задаёт число связей на узел графа. При M = 40 граф добавляет 160 байт на вектор. Для типового эмбеддера на 1536 измерений это меньше 3% от объёма самих векторов: на высоких размерностях память съедает не индекс, а сырые данные.

Вернёмся к базе знаний из вступления. 50 000 документов при разбиении на чанки по 500–800 токенов дают примерно 1 млн векторов. Вот что получается на разных конфигурациях.

Корпус Размерность Сырые векторы Граф HNSW (M = 40) Итого RAM С int8-квантованием
1 млн 1536 6,1 ГБ 0,16 ГБ ~6,3 ГБ ~1,7 ГБ
10 млн 1536 61 ГБ 1,6 ГБ ~63 ГБ ~17 ГБ
100 млн 1536 614 ГБ 16 ГБ ~630 ГБ ~170 ГБ
10 млн 1024 41 ГБ 1,6 ГБ ~43 ГБ ~12 ГБ

Цифры считаются арифметикой, а не берутся из обзоров: колонки сырых векторов и графа выводятся из формулы выше, «итого» — их сумма, а последняя колонка — тот же расчёт при одном байте на измерение вместо четырёх. Читать таблицу стоит так.

  • 1 млн векторов помещается на одну машину без ухищрений. Здесь спор о том, какой движок быстрее, почти не имеет практического смысла: и специализированная векторная база данных, и расширение поверх PostgreSQL справятся.
  • 10 млн — точка, где начинается инженерия. 63 ГБ означают отдельный сервер под индекс. Дешевле сначала попробовать квантование, чем менять движок.
  • 100 млн — другой класс задачи. 630 ГБ в оперативной памяти одной ноды не держат: нужны шардирование, дисковые индексы или оба приёма сразу.
  • Размерность эмбеддера — рычаг, который забывают. Переход с 1536 на 1024 измерения экономит треть памяти на всём корпусе, причём качество на конкретном домене может не измениться.

Квантование: главный рычаг стоимости

Квантование сжимает вектор, заменяя float32 на более компактное представление. Скалярное квантование (float32 → int8) даёт четырёхкратное сжатие при умеренном снижении recall, бинарное сжимает сильнее, и тем заметнее падает точность. В Qdrant 1.18 появился метод TurboQuant: вендор заявляет восьмикратное сжатие при сопоставимых recall и скорости относительно скалярного квантования. Заявка не подтверждена независимым замером, поэтому проверять её стоит на своих данных.

Механика, которая делает квантование рабочим, называется rescoring. Поиск идёт в два прохода: грубый по сжатым векторам отбирает кандидатов, точный по исходным float32 переупорядочивает верхушку выдачи. Weaviate измерил это на 1 млн эмбеддингов OpenAI размерности 1536: без rescoring 8-битное квантование теряет recall, с rescoring по топ-20 качество восстанавливается. Хранить исходные векторы при этом всё равно нужно, но уже на диске, а не в оперативной памяти.

Когда индекс уезжает на диск

Ограничение HNSW в том, что граф должен целиком лежать в RAM. Обходят его дисковыми индексами.

  • StreamingDiskANN в расширении pgvectorscale держит часть индекса на диске и растягивает применимость PostgreSQL до сотен миллионов векторов.
  • Qdrant предлагает low memory mode с принудительным хранением на диске и inline-хранение HNSW, которое снижает нагрузку на ввод-вывод.
  • Milvus поддерживает DiskANN, а журнал предзаписи Woodpecker в версии 2.6 уносит лог в объектное хранилище, оставляя метаданные в распределённом KV.

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

Почему публичным бенчмаркам векторных БД верить нельзя

Обзоры обычно ссылаются на два инструмента, и они меряют разные вещи.

Инструмент Что меряет Кто ведёт
ann-benchmarks Алгоритмы ANN (HNSW, IVF, DiskANN) на стандартных датасетах SIFT-1M, GloVe-100, Deep-1B. Результат — кривая recall против QPS Открытое сообщество
VectorDBBench Системы целиком: пропускная способность вставки, масштабирование, конкурентные запросы, утилизация ресурсов на 30+ базах Zilliz, компания за Milvus

Разграничение фиксирует и сам вендор: ann-benchmarks про сырую производительность алгоритмов, VectorDBBench про end-to-end возможности базы. Отсюда два вывода, которые меняют чтение любого лидерборда.

ann-benchmarks меряет не базу данных. В нём нет вставки под нагрузкой, нет фильтрации по метаданным, нет конкурентных запросов и нет сети. Библиотека индексов может выигрывать кривую recall/QPS и проигрывать в проде, где половина запросов приходит с условием WHERE department = 'hr'.

VectorDBBench ведёт заинтересованная сторона. Zilliz — компания-разработчик Milvus, и это прямой конфликт интересов, а не формальная придирка. В 2026 году в инструмент добавили Cloud Leaderboard со сценариями CloudInsertCase, CloudPayloadSearchCase, CloudMultiTenantSearchCase и CloudColdLatencyCase. Набор сценариев полезный, но выбирает их тот же вендор.

Проблема шире одного инструмента. Бенчмарки создают видимость объективности, но кодируют архитектурные допущения авторов: VectorDBBench вознаграждает распределённое масштабирование, наборы вокруг Redis и Qdrant делают акцент на in-memory операциях. Есть и академическая попытка это исправить: препринт VIBE (Vector Index Benchmark for Embeddings) предлагает мерить на реальных эмбеддингах вместо синтетических SIFT и GloVe.

Вендорские заявки полезно читать с той же оптикой. Milvus в превью версии 2.6 заявил сокращение памяти на 72% без потери recall и четырёхкратное преимущество над Elasticsearch. Расширение pgvectorscale от Timescale (Tiger Data) ещё в 2024 году отчиталось о замере на 50 млн эмбеддингов Cohere размерности 768. В сравнении со storage-optimized индексом Pinecone заявлены латентность p95 ниже в 28 раз, пропускная способность выше в 16 раз при recall 99% и стоимость на 75% ниже. Каждая из этих цифр получена вендором на своей конфигурации против прямого конкурента, независимого подтверждения множителей найти не удалось.

Что из бенчмарков можно взять, не соврав читателю. У зрелых движков recall на типовых датасетах близок к единице. Различия смещаются в латентность, стоимость памяти и поведение под фильтрами, а абсолютных рейтингов вида «топ-1 векторная база данных 2026» публичные замеры не дают. Единственный замер, на который стоит опираться при выборе, — прогон на своём корпусе, своих фильтрах и своём профиле нагрузки.

Сравнение векторных баз данных: Qdrant, pgvector, Milvus и Weaviate

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

Параметр Qdrant pgvector Milvus Weaviate
Тип и реализация Отдельная СУБД на Rust Расширение PostgreSQL Распределённая СУБД на Go и C++, K8s-native Отдельная СУБД на Go
Актуальная линия 1.18.x 0.8.5, релиз 08.07.2026 (в линии 0.8; версия 0.8.2 вышла 25.02.2026) 2.6.x (последний патч — 2.6.21, июль 2026); версия 3.0 объявлена общедоступной 16.07.2026, но тега 3.0.0 в GitHub Releases на 27.07.2026 нет — только 3.0.0-beta 1.38.x (последняя стабильная линия; 1.39 — в статусе release candidate)
Индексы HNSW, ACORN-1 для фильтрованного поиска HNSW и IVFFlat HNSW, IVF, FLAT, SCANN, DiskANN HNSW, HFresh (preview)
Гибридный поиск Взвешенный RRF с версии 1.17 Нет из коробки, собирается вручную на tsvector Есть BM25 и вектор с параметром alpha от 0.0 до 1.0
Фильтрация по метаданным Сильная сторона движка, ACORN-1 для точного поиска под фильтром Обычным WHERE; с версии 0.8 работают iterative index scans Есть Есть
Мультитенантность Tenant promotion с версии 1.16 Схемой и row-level security Есть Есть
Рекомендуемый масштаб От 1 млн до сотен млн векторов До ~10 млн; с pgvectorscale выше От 10 млн до миллиардов Средний масштаб
Операционная сложность Низкая: один сервис Нулевая, если PostgreSQL уже в проде Высокая: распределённая система с обвесом Средняя
Self-hosted Да Да Да Да
Доступность в VK Cloud Развёртывание из Магазина приложений Отсутствует в опубликованном списке расширений Managed PostgreSQL Развёртывание из Магазина приложений В документации не описан

Лицензии ядра на 27 июля 2026 года: Qdrant и Milvus — Apache 2.0, Weaviate — BSD-3-Clause, pgvector — лицензия PostgreSQL. Все четыре разрешают коммерческое использование, но условия платных редакций и облачных сервисов у вендоров свои — их сверяйте отдельно.

Когда хватает pgvector

Если PostgreSQL уже работает в проде, а корпус меньше 10 млн векторов, отдельная векторная база данных чаще всего избыточна. Векторы лежат в той же транзакции, что и бизнес-данные, фильтры пишутся обычным SQL, бэкап и мониторинг уже настроены. Линия 0.8 закрыла главную болезнь фильтрованного поиска: iterative index scans досканируют индекс, пока не наберётся нужное число строк, прошедших WHERE.

Границы у этого варианта жёсткие. Расширение работает на CPU, нативной поддержки GPU и DiskANN в нём нет, а векторная нагрузка ложится на тот же кластер, который обслуживает транзакции. На десятках миллионов векторов и тысячах запросов в секунду поведение деградирует. Лимит типа vector — 16 000 измерений, но HNSW и IVFFlat индексируют не больше 2 000. Половинная точность (halfvec) поднимает потолок индекса до 4 000, бинарная квантизация — до 64 000.

Важная оговорка для тех, кто планирует этот сценарий в облаке: в опубликованном списке расширений Managed PostgreSQL VK Cloud pgvector отсутствует. Список закрытый и приведён в документации целиком, поэтому такой путь придётся строить на собственном PostgreSQL, а не на управляемой базе. Сверка выполнена 27 июля 2026 года.

Когда выбирать Qdrant

Qdrant уместен, когда фильтрация не второстепенна, а составляет половину задачи: поиск в пределах отдела, тенанта или уровня доступа. Под это в движке сделаны отдельные механизмы — алгоритм ACORN-1 для точного поиска под фильтром и tenant promotion для многоуровневой мультитенантности.

Второй аргумент — операционная простота. Это один сервис, который поднимается из контейнера и не тянет за собой очередь сообщений, координатор и объектное хранилище. Гибридный поиск на взвешенном RRF (reciprocal rank fusion) приехал в версии 1.17, там же появился audit access logging.

При обновлении с версий младше 1.17 учитывайте breaking change: формат ответа для векторных полей в gRPC изменился, старые поля объявлены устаревшими. Клиентский код придётся править.

Когда нужен Milvus

Milvus имеет смысл от десятков миллионов векторов и выше, когда одной ноды перестаёт хватать, а держать распределённую систему есть кому. Набор индексов у него шире всех в подборке, включая SCANN и DiskANN, а индексация умеет уезжать на GPU. Плата — операционная сложность: это распределённая система, которую разворачивают и обслуживают в Kubernetes. Журнал предзаписи Woodpecker в версии 2.6 частично снимает эту нагрузку, унося лог в объектное хранилище и убирая необходимость в отдельной Kafka или Pulsar.

Отдельно про версии: со статусом Milvus 3.0 источники расходятся. Превью 3.0.0-beta вышло 9 мая 2026 года. А 16 июля 2026 года вендор объявил Milvus 3.0 общедоступным: под Apache 2.0, с развёртыванием в Kubernetes и Docker и SDK для Python, Go и Node.js. Однако в GitHub Releases проекта на 27 июля 2026 года тега 3.0.0 нет: последний стабильный релиз репозитория — 2.6.21 из линии 2.6.x. Практический вывод: сверяйте статус на дату своего решения, а продовой линией пока остаётся 2.6.x.

blog_800x400_6041a73bf6.jpg

Разверните Qdrant или Milvus в VK Cloud и запустите векторный поиск для своей RAG-системы

Где уместен Weaviate

Weaviate закрывает сценарий, в котором гибридный поиск нужен из коробки и без ручной сборки. Параметр alpha задаёт баланс между ключевыми словами (0.0) и вектором (1.0), значение 0.5 даёт равный вклад. В версии 1.37 в движок встроили MCP-сервер (Model Context Protocol), в том числе инструмент гибридного поиска, что упрощает подключение к агентным сценариям. В версии 1.36 в статусе preview появился индекс HFresh, а server-side batching и Object TTL переведены в общедоступный статус (GA).

Ограничение не в отсутствии распределённого режима: шардирование коллекции по нодам появилось в Weaviate 1.8, репликация задаётся фактором на коллекцию или глобально. Разница с Milvus в другом — в наборе индексов (DiskANN и SCANN, индексация на GPU) и в том, как разнесены хранение и вычисление. На миллиардах векторов Weaviate ему уступает. В документации VK Cloud он не описан, поэтому в облаке это self-hosted-сценарий.

Матрица выбора по сценариям

Типовые сценарии выбора векторной базы данных и подходящие под них движки выглядят так.

Если у вас Берите Почему
PostgreSQL в проде и меньше 10 млн векторов Расширение pgvector на своём кластере Ноль нового в стеке, фильтры обычным SQL
Жёсткая фильтрация по ACL или тенантам, до сотен млн векторов Qdrant ACORN-1, tenant promotion, один сервис в эксплуатации
Десятки и сотни млн векторов, готовность держать Kubernetes Milvus Шардирование, DiskANN, GPU-индексация
Нужен гибридный поиск без ручной сборки Weaviate BM25 и вектор одним запросом через alpha
Меньше 1 млн векторов и никаких особых требований Что угодно из списка На этом масштабе разница между движками не окупает миграцию

Фильтры, гибридный поиск и reranking: где на самом деле лежит качество

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

Overfiltering: когда фильтр съедает выдачу

Overfiltering возникает из-за порядка операций: приближённый поиск сначала находит K ближайших соседей, а фильтр применяется уже к ним. Если условие отсекает почти всех кандидатов, результатов не остаётся: система вернёт две строки вместо десяти, а LLM ответит «не нашёл». Проблема архитектурная и лечится на уровне индекса. В pgvector 0.8 это делают iterative index scans, которые досканируют индекс до нужного числа отфильтрованных строк, в Qdrant — алгоритм ACORN-1. Если в вашем RAG фильтры по правам доступа обязательны, проверять кандидатов стоит именно на этом сценарии, а не на чистом векторном поиске.

Гибридный поиск и переранжирование

Допущение «семантический поиск всегда выигрывает у полнотекстового» не выдерживает проверки. В препринте про retrieval на документах с таблицами BM25 обошёл плотный поиск на эмбеддингах OpenAI text-embedding-3-large по всем метрикам, кроме Recall@20, где результаты практически сравнялись (0,797 против 0,798). Объяснение прозаичное: в финансовых и юридических документах много точных идентификаторов, номеров и терминов, по которым лексический матч работает лучше усреднённого вектора.

Отсюда стандартная схема 2026 года: параллельно идут лексический и векторный поиск, выдачи сливаются алгоритмом вроде RRF, а затем cross-encoder переранжирует верхушку. Эффект измерен на бенчмарке T2-RAGBench — 23 088 запросов к 7 318 документам с текстом и таблицами. Двухступенчатая схема «гибрид плюс нейросетевой reranker» дала Recall@5 0,816 против 0,695 у чистого гибрида на RRF: плюс 17,4% относительно и лучший результат среди десяти проверенных стратегий.

Бюджет инженерного времени разумнее потратить на гибридный поиск и reranker, чем на миграцию между векторными базами.

Эмбеддер важнее движка, а его смена дороже

Качество retrieval определяется прежде всего моделью, которая строит векторы. Лидерборд MTEB (Massive Text Embedding Benchmark) перетасовывается за недели. Qwen3-Embedding-8B занимал первое место в multilingual-подмножестве с баллом 70,58 на 5 июня 2025 года. Это утверждение о конкретной дате, а не о текущем положении дел.

Общий балл MTEB для выбора эмбеддера подходит плохо: это агрегат по классификации, кластеризации, retrieval и семантической близости. Высокая суммарная оценка не гарантирует лучший retrieval на вашем домене. Сравнивать модели стоит по retrieval-подмножеству и на своих документах.

Для русскоязычных корпоративных документов выбор ещё уже. Отраслевые обзоры называют BGE-M3 и Cohere embed-v4 заметно более точными на кириллице. Но специализированного русскоязычного retrieval-бенчмарка, аналогичного MTEB, в открытом доступе найти не удалось. Это практика, а не измеренный факт: перед продом стоит прогнать 200–300 реальных запросов вашей поддержки через две-три модели и сравнить Recall@5 руками.

Отдельная статья расходов, о которой обзоры молчат: смена эмбеддера требует полной переиндексации корпуса. Для 10 млн векторов это часы GPU и простой поиска. Модель выбирают до того, как заливают корпус, а не после.

Развернуть векторную базу данных и инференс-контур для RAG можно в VK Cloud: Qdrant и Milvus доступны как готовые развёртывания из Магазина приложений, а под инференс эмбеддера и reranker'а в Cloud Containers есть GPU-ноды с аддоном GPU Operator.

Запуск Qdrant в VK Cloud: пошаговое руководство

Qdrant и Milvus в VK Cloud разворачиваются из Магазина приложений: мастер поднимает сервис на выделенной виртуальной машине и выдаёт готовые доступы. Порядок такой.

  1. Подготовьте сеть. Если сервис должен быть доступен снаружи, создайте сеть с выходом в интернет и отключите опцию «Приватный DNS» в настройках подсети.
  2. Откройте карточку сервиса. Раздел Магазин приложений → карточка QdrantПодробнееПодключить.
  3. Выберите тип размещения. Значение external даёт внешний IP и доменное имя от платформы, internal оставляет доступ только внутри VK Cloud. Для продовой базы знаний обычно берут internal и ходят к ней из своего кластера.
  4. Включите резервное копирование на S3. Опция создаёт ежедневные копии данных Qdrant в объектном хранилище. Хранилище создаётся автоматически, сохраняются последние семь копий. Про разницу моделей хранения — в разборе.
  5. Включите мониторинг. Метрики виртуальной машины уходят в Cloud Monitoring и видны в разделе «Мониторинг» личного кабинета.
  6. Задайте параметры машины и дисков. Сеть, зона доступности, тип виртуальной машины, размер диска и его тип: HDD, SSD или High-IOPS SSD. Под HNSW-индекс в RAM тип диска вторичен, но при включённом on-disk хранении векторов разница между SSD и High-IOPS SSD становится заметной.
  7. Подтвердите тариф. Мастер показывает стоимость инфраструктуры перед подключением. После развёртывания приходят два письма: уведомление со ссылкой на инстанс в личном кабинете и письмо с одноразовой ссылкой на доступы. Из неё нужно сразу сохранить три значения: qdrant_url (адрес API), api_key (ключ подключения) и keypair (приватный ключ для SSH к машине). Ссылка одноразовая, но тупика при потере доступов нет: документация предусматривает выпуск новых, не описывая процедуру подробно. Веб-интерфейс открывается по адресу <АДРЕС_СЕРВИСА>/dashboard, где адрес берётся из qdrant_url, а в поле ключа указывается api_key.

Чего развёртывание из Магазина приложений не даёт

Три ограничения, о которых стоит знать до проектирования архитектуры.

  • Это развёртывание на выделенной ВМ, а не управляемый сервис. Документация не называет Qdrant и Milvus из Магазина приложений управляемыми сервисами и не заявляет для них SLA. Обновление версии, тюнинг и восстановление остаются на вашей стороне.
  • Описан один инстанс, а не шардированный кластер. Шардирование и репликацию Qdrant умеет сам, но сценарий многонодового кластера в документации Магазина приложений не разобран. Для корпуса, который не помещается в одну машину, план развёртывания придётся строить самостоятельно.
  • Расширения pgvector в Managed PostgreSQL нет. Опубликованный список расширений закрытый, и pgvector в него не входит. Сценарий «векторы рядом с бизнес-данными в управляемой базе» на этой платформе не собирается: понадобится собственный PostgreSQL на виртуальной машине или в кластере. Про выбор самой СУБД под задачу — в.

Self-hosted: разработка и кластерные сценарии

Для локальной разработки хватает контейнера. Версию образа фиксируйте явно: тег latest однажды приедет с breaking change.

# docker-compose.yml services: qdrant: image: qdrant/qdrant:v1.18.3 ports: - "6333:6333" # REST API и веб-интерфейс - "6334:6334" # gRPC volumes: - ./qdrant_storage:/qdrant/storage

Если сценарий требует своей конфигурации или нескольких реплик, Qdrant ставят Helm-чартом проекта в кластер Cloud Containers — так в VK Cloud называется сервис управляемого Kubernetes. Helm при этом идёт компонентом кластера с закреплённой версией, отдельный аддон для него не нужен. Три вещи, на которых спотыкаются при первом развёртывании.

  • Класс хранения по умолчанию в кластерах не настроен, поэтому storageClassName указывают в каждом PVC явно, например csi-high-iops-ms1 для зоны MS1.
  • Режим доступа ReadWriteMany не реализован. Для векторной базы это не блокер: каждая реплика Qdrant работает со своим томом через StatefulSet и режим ReadWriteOnce.
  • Публикация наружу идёт через Ingress Controller (NGINX) или LoadBalancer, и в обоих случаях создаётся тарифицируемый балансировщик платформы.

Снапшоты и бэкапы удобно складывать в VK Object Storage: эндпоинт региона Москва — https://hb.ru-msk.vkcloud-storage.ru, код региона для подписи запроса ru-msk. У совместимости с AWS S3 API есть границы: часть методов не реализована и возвращает ошибку NotImplemented, поэтому нужный вам метод стоит сверить с документацией. Версионирование бакета при этом поддерживается: оно включается в личном кабинете или через AWS CLI и применяется ко всем объектам бакета, а перезапись и удаление не стирают предыдущие версии — вместо удаления в бакет добавляется маркер удаления. Для схемы «бэкапы в S3» это важнее совместимости по методам. Подробнее про схемы резервного копирования — в материале про.

Практика: индексирование документов и поиск

Дальше — минимальный рабочий контур на официальном клиенте qdrant-client. Адрес и ключ берутся из qdrant_url и api_key, которые пришли в письме с доступами.

Создание коллекции

Размерность вектора задаётся на этапе создания и потом не меняется, как и метрика расстояния. Ошибка здесь стоит полной переиндексации, поэтому размерность берут из карточки выбранного эмбеддера, а не по памяти.

from qdrant_client import QdrantClient from qdrant_client.models import ( Distance, VectorParams, PayloadSchemaType, ScalarQuantization, ScalarQuantizationConfig, ScalarType, ) client = QdrantClient(url=QDRANT_URL, api_key=API_KEY) client.create_collection( collection_name="kb_docs", vectors_config=VectorParams( size=1024, # размерность эмбеддера, здесь BGE-M3 distance=Distance.COSINE, on_disk=True, # исходные float32 — на диск, иначе они останутся в RAM ), # int8-квантование сжимает векторы примерно вчетверо, # always_ram=True держит в памяти сжатую копию, # исходные float32 читаются с диска на этапе rescoring quantization_config=ScalarQuantization( scalar=ScalarQuantizationConfig( type=ScalarType.INT8, always_ram=True, ) ), ) # Индекс по полю, по которому пойдёт фильтр. Без него фильтрация # сваливается в перебор, а ACORN нечем пользоваться. client.create_payload_index( collection_name="kb_docs", field_name="department", field_schema=PayloadSchemaType.KEYWORD, )

Пара on_disk=True плюс always_ram=True даёт ровно ту конфигурацию, на которой сходится колонка «с int8-квантованием» из таблицы памяти. В оперативной памяти лежат сжатая копия и граф, а исходные векторы читаются с диска только при переранжировании верхушки. Без on_disk=True оригиналы останутся в RAM и экономии не будет.

Параметры HNSW (m, ef_construct) задаются здесь же через hnsw_config. Начинать стоит с дефолтов из документации Qdrant и менять их только после замера на своих данных: рекомендации из обзоров приводятся вразнобой и без описанной методики.

Загрузка векторов пачками

Заливать по одному вектору дорого: каждый запрос платит за сеть и построение графа. Пачки по 256–1000 точек снимают основную часть накладных расходов.

from qdrant_client.models import PointStruct def upload(chunks, embed, batch_size=512): """chunks: список dict с полями text, doc_id, department, updated_at.""" for start in range(0, len(chunks), batch_size): batch = chunks[start:start + batch_size] vectors = embed([c["text"] for c in batch]) # один вызов на пачку client.upsert( collection_name="kb_docs", points=[ PointStruct( id=start + i, vector=vector, payload={ "text": chunk["text"], "doc_id": chunk["doc_id"], "department": chunk["department"], "updated_at": chunk["updated_at"], }, ) for i, (chunk, vector) in enumerate(zip(batch, vectors)) ], wait=False, # не ждать индексацию на каждой пачке )

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

Поиск с фильтрацией по метаданным

Поиск с фильтром по метаданным — главный сценарий проверки на overfiltering: вопрос сотрудника ищется только по документам его отдела.

from qdrant_client.models import ( Filter, FieldCondition, MatchValue, SearchParams, AcornSearchParams, ) def search(question, department, top_k=5): query_vector = embed([question])[0] result = client.query_points( collection_name="kb_docs", query=query_vector, query_filter=Filter( must=[ FieldCondition( key="department", match=MatchValue(value=department), ) ] ), # ACORN включается явно: по умолчанию enable=False, # и по умолчанию же он не применяется к фильтрам с оценкой # селективности выше 0.4 — порог меняется max_selectivity search_params=SearchParams( acorn=AcornSearchParams(enable=True), ), limit=top_k, with_payload=True, ) return [(p.score, p.payload["text"]) for p in result.points]

Проверить конвейер на overfiltering просто: прогоните те же запросы с фильтром и без него, затем сравните, сколько результатов реально вернулось. Если под фильтром выдача регулярно короче top_k, разбирайтесь с настройками индекса, а не с эмбеддером.

Сигнатуры сверены с README официального клиента qdrant-client на 27 июля 2026 года. Учтите версию клиента: query_points доступен начиная с 1.10, в более старых версиях тот же сценарий пишется через search.

Что в итоге считать перед выбором

Выбор векторной базы данных опирается на три числа и один замер. Числа: размер корпуса в векторах, размерность эмбеддера и объём доступной оперативной памяти. Они закрывают вопрос «нужна ли отдельная база» ещё до чтения обзоров. До 10 млн векторов достаточно расширения на работающем PostgreSQL, выше начинается специализированный движок, а на сотнях миллионов и дальше вопрос переходит в многонодовое развёртывание. Шардирование и репликацию умеют все три специализированных движка из подборки — выбор между ними решает не факт распределённости, а операционная цена и набор индексов. Замер, который не заменяется лидербордом, ровно один: прогон на своих документах и своих фильтрах.

Самый дешёвый прирост качества RAG дают гибридный поиск и reranking, а не миграция между движками. Сам поиск — лишь один из слоёв большей системы: как он встраивается в общую схему, разобрано в материале про. Начните с расчёта памяти, и векторная база данных под задачу подберётся почти однозначно.

Частые вопросы про векторные базы данных

Что такое векторная база данных?

Векторная база данных — хранилище, которое держит эмбеддинги (числовые представления текста, изображений или аудио) и ищет среди них ближайших соседей по метрике расстояния вроде cosine similarity. Обычная СУБД ищет по точному совпадению или подстроке, векторная — по смысловой близости. Внутри лежат три сущности: сам вектор из 768–4096 чисел float32, метаданные для фильтрации и ANN-индекс, чаще всего граф HNSW.

Чем Qdrant лучше pgvector?

В общем случае ничем: это разные классы решений. Qdrant выигрывает там, где нужны продвинутая фильтрация под мультитенантность, гибридный поиск из коробки и масштаб выше 10 млн векторов. Расширение pgvector выигрывает там, где PostgreSQL уже в проде: векторы живут в одной транзакции с бизнес-данными, а бэкап и мониторинг не нужно строить заново. На корпусе меньше миллиона векторов разница между ними обычно не окупает миграцию.

Что такое RAG-система?

RAG (retrieval-augmented generation) — схема, в которой языковая модель отвечает не по памяти, а по найденным фрагментам ваших документов. Конвейер состоит из четырёх шагов: документы режутся на чанки и кодируются эмбеддером в векторы, вопрос кодируется тем же эмбеддером, векторная база находит топ-K ближайших чанков, найденное вместе с вопросом уходит в модель. Так ответ опирается на актуальные внутренние данные, а источники можно показать пользователю.

Сколько векторов умещается в Qdrant на одном сервере?

Считается арифметикой, а не берётся из спецификации. Один вектор занимает размерность × 4 байта плюс M × 4 байта на граф HNSW: при 1536 измерениях и M = 40 это примерно 6,3 КБ на вектор. Машина со 128 ГБ оперативной памяти вмещает по этой арифметике около 20 млн таких векторов без квантования и около 75 млн с int8-квантованием — и это потолок, из которого ещё нужно вычесть запас на операционную систему и сам процесс. Снизить расход помогают эмбеддер меньшей размерности и хранение исходных векторов на диске.

⚙️ Верстальщику: разметку ниже вставьте в страницу внутри тега script type="application/ld+json".

{ "@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [ { "@type": "Question", "name": "Что такое векторная база данных?", "acceptedAnswer": { "@type": "Answer", "text": "Векторная база данных — хранилище, которое держит эмбеддинги (числовые представления текста, изображений или аудио) и ищет среди них ближайших соседей по метрике расстояния вроде cosine similarity. Обычная СУБД ищет по точному совпадению или подстроке, векторная — по смысловой близости. Внутри лежат три сущности: сам вектор из 768–4096 чисел float32, метаданные для фильтрации и ANN-индекс, чаще всего граф HNSW." } }, { "@type": "Question", "name": "Чем Qdrant лучше pgvector?", "acceptedAnswer": { "@type": "Answer", "text": "В общем случае ничем: это разные классы решений. Qdrant выигрывает там, где нужны продвинутая фильтрация под мультитенантность, гибридный поиск из коробки и масштаб выше 10 млн векторов. Расширение pgvector выигрывает там, где PostgreSQL уже в проде: векторы живут в одной транзакции с бизнес-данными, а бэкап и мониторинг не нужно строить заново. На корпусе меньше миллиона векторов разница между ними обычно не окупает миграцию." } }, { "@type": "Question", "name": "Что такое RAG-система?", "acceptedAnswer": { "@type": "Answer", "text": "RAG (retrieval-augmented generation) — схема, в которой языковая модель отвечает не по памяти, а по найденным фрагментам ваших документов. Конвейер состоит из четырёх шагов: документы режутся на чанки и кодируются эмбеддером в векторы, вопрос кодируется тем же эмбеддером, векторная база находит топ-K ближайших чанков, найденное вместе с вопросом уходит в модель. Так ответ опирается на актуальные внутренние данные, а источники можно показать пользователю." } }, { "@type": "Question", "name": "Сколько векторов умещается в Qdrant на одном сервере?", "acceptedAnswer": { "@type": "Answer", "text": "Считается арифметикой, а не берётся из спецификации. Один вектор занимает размерность × 4 байта плюс M × 4 байта на граф HNSW: при 1536 измерениях и M = 40 это примерно 6,3 КБ на вектор. Машина со 128 ГБ оперативной памяти вмещает по этой арифметике около 20 млн таких векторов без квантования и около 75 млн с int8-квантованием — и это потолок, из которого ещё нужно вычесть запас на операционную систему и сам процесс. Снизить расход помогают эмбеддер меньшей размерности и хранение исходных векторов на диске." } } ] }

Оставьте заявку, чтобы получить консультацию

section_subscribe_2x_9ab2d878a6.png

            Узнавайте о выходе новых статей в блоге первыми!

            Будем держать в курсе новостей и облачных трендов

            section-subscribe_2x.png
              section-subscribe_2x.png
              Ссылка скопирована
              Поделиться

              Почитать по теме

              _blog_head_172.png
              18 августа

              Как организовать хранение медицинских данных для ИИ с учетом требований российского законодательства

              _blog_head_131.png
              13 августа

              Объектное, файловое и блочное хранилище: в чём разница и что выбрать под задачу

              blog_head_39_69.png
              13 августа

              Горячее, холодное и архивное хранение в S3: классы и автоматизация lifecycle

              40+ готовых сервисов