Векторные базы данных — один из самых горячих классов инструментов последних лет. Интерес к ним вырос вместе с LLM и RAG-паттерном, но сами по себе векторные индексы и поиск по сходству (similarity search) существуют куда дольше нынешнего хайпа. Поэтому правильный вопрос — не «нужна ли мне векторная БД», а какую именно задачу она решает и где более простые альтернативы справляются не хуже.
Эта статья — не каталог движков и не бенчмарк с цифрами. Она про то, как подходить к выбору инженерно: понимать, что стоит за словом «эмбеддинг», почему приблизительный поиск — это осознанный компромисс, а не недостаток, и по какой лестнице вопросов двигаться прежде чем тянуть в стек отдельное хранилище. Это вход в серию: каждый слой — эмбеддинги, ANN-индексы, конкретные движки — планируется разобрать отдельно и вглубь в следующих статьях.
В статье
- Что такое эмбеддинг и семантический поиск
- Приблизительный поиск — это компромисс
- Нужна ли вообще: лестница выбора
- Типичные ошибки — они же «когда не нужны»
- Куда дальше
Что такое эмбеддинг и семантический поиск
В основе всего лежит одна идея: модель превращает текст, картинку или аудио в вектор — точку в пространстве из нескольких сотен или тысяч измерений. Это и есть эмбеддинг. Ключевое свойство, ради которого всё затевается: смысловая близость превращается в геометрическую. «Кот» и «кошка» окажутся точками рядом друг с другом, а «кот» и «квартальный отчёт» — далеко. Найти похожее по смыслу теперь означает найти ближайшие точки в этом пространстве — это и называют семантическим поиском, в отличие от поиска по точному совпадению слов.
Размерность вектора — 384, 768, 1536 и другие похожие числа, которые встречаются в описаниях моделей, — это просто количество чисел, которыми описана точка. Большая размерность даёт модели больше ёмкости под оттенки смысла, но сама по себе качества не гарантирует: насколько хорошо ловится смысл, зависит от модели, её обучения, домена, языка и метрики близости, и проверяется только на конкретной задаче. При этом каждое лишнее измерение — это дополнительная память и вычисления на каждый вектор, так что «больше» не значит «лучше по умолчанию». Как именно эти числа получаются внутри модели и почему близость измеряют косинусом или евклидовым расстоянием — детали, которые для выбора инструмента не обязательны; здесь достаточно интуиции «данные стали точками, похожее — рядом».
Эмбеддинги для русскоязычной аудитории. Основной путь — открытые мультиязычные модели с Hugging Face, которые поднимаются у себя: например, multilingual-e5 или BGE-M3. Запускают их обычно через Sentence Transformers или родные библиотеки вроде FlagEmbedding. Они работают с русским языком и не привязывают проект к конкретному облаку; за сам доступ к модели платить не нужно, но инференс на своих GPU или CPU — это уже своя эксплуатационная стоимость, которую стоит закладывать. Удобная альтернатива — российские облачные API, например GigaChat Embeddings или YandexGPT Embeddings: не нужно поднимать инфраструктуру, но появляется зависимость от внешнего сервиса и плата за запросы. Как ещё один вариант — зарубежные API вроде OpenAI или Cohere. Какой из вариантов точнее именно на ваших текстах — вопрос, который решается замером на своём датасете, а не общими рекомендациями: у моделей разные сильные стороны по языкам и доменам. Выбор конкретной модели, её обновление и то, как со временем «плывут» уже посчитанные эмбеддинги, — тема отдельного разговора: эмбеддинги в проде: выбор модели, дрейфСкоро.
Приблизительный поиск — это компромисс
Раз данные стали точками, найти похожее можно в лоб: сравнить запрос с каждой точкой в базе и взять ближайшие. Это точный поиск (exact kNN), и с ним есть одна проблема — сравнение со всеми линейно дорожает по мере роста числа векторов. На практике вместо этого почти всегда используют приблизительный поиск (ANN, approximate nearest neighbors): он находит почти всех нужных соседей на порядки быстрее точного перебора, но время от времени кого-то из по-настоящему ближайших пропускает.
Именно этот размен — точность против скорости и памяти — и есть центральная тема всей области векторного поиска. Крутить его ручки в ту или иную сторону приходится в любом проекте, который выбирает векторную БД или индекс: чуть точнее — чуть медленнее и прожорливее по памяти, и наоборот. Как именно устроены индексы вроде HNSW и IVF и что делает с векторами квантизация — отдельный и более глубокий разговор: ANN вглубь: HNSW, IVF, PQСкоро.
Нужна ли вообще: лестница выбора
Правильный порядок вопросов — не «какую векторную БД взять», а «нужен ли тут вообще поиск по смыслу, а если да — хватит ли того, что уже стоит в стеке». Это лестница из трёх ступеней, и подниматься по ней стоит снизу вверх.
а не по совпадению слов?"] -->|"Нет"| B["Полнотекстовый поиск,
теги, фильтры"] A -->|"Да"| C{"Объём и требования"} C -->|"Порядка миллиона векторов,
низкий/средний QPS, простые фильтры,
PG или OpenSearch уже есть"| D["Встроенное:
pgvector / k-NN / Redis"] C -->|"Миллионы+, гибрид,
фильтрация, SLA"| E["Выделенная:
Qdrant / Milvus / Weaviate"]
flowchart TD
A["Нужен поиск по смыслу,
а не по совпадению слов?"] -->|"Нет"| B["Полнотекстовый поиск,
теги, фильтры"]
A -->|"Да"| C{"Объём и требования"}
C -->|"Порядка миллиона векторов,
низкий/средний QPS, простые фильтры,
PG или OpenSearch уже есть"| D["Встроенное:
pgvector / k-NN / Redis"]
C -->|"Миллионы+, гибрид,
фильтрация, SLA"| E["Выделенная:
Qdrant / Milvus / Weaviate"]
Часто не нужна вовсе
Если задачу решают полнотекстовый поиск, теги и атрибутивные фильтры, векторы только добавят сложности. Векторный поиск оправдан там, где важен смысл, а не совпадение слов: «похожие товары», «найди по описанию своими словами», семантический FAQ. Если такой задачи нет — нет и повода тянуть в стек векторную БД.
Встроенного часто хватает
Если PostgreSQL уже стоит в проекте, pgvector добавляет векторный поиск той же командой SQL, в той же транзакции, с тем же бэкапом — без нового stateful-компонента в инфраструктуре. На практике это выглядит буквально как ещё одна колонка и ORDER BY по расстоянию:
CREATE EXTENSION IF NOT EXISTS vector;
-- вектор живёт обычной колонкой рядом с остальными полями таблицы
CREATE TABLE documents (
id bigserial PRIMARY KEY,
title text,
lang text,
embedding vector(768) -- 768 — размерность выбранной модели эмбеддингов
);
-- эмбеддинг кладётся тем же INSERT/UPDATE, что и любое другое поле
UPDATE documents SET embedding = :embedding WHERE id = :id;
-- поиск похожих: ORDER BY по расстоянию, <=> — косинусное расстояние.
-- Обычные WHERE-фильтры и JOIN работают ровно как всегда.
-- Без индекса это точный перебор (exact scan); индексы HNSW/IVFFlat — дальше в серии.
SELECT id, title
FROM documents
WHERE lang = 'ru'
ORDER BY embedding <=> :query_embedding
LIMIT 10;Никакого отдельного клиента, протокола или сервиса — тот же коннект к Postgres, что и для всего остального. То же касается k-NN в OpenSearch или векторного поиска в Redis, если один из них уже есть в стеке. Практический порог здесь — это порядок величины, а не точное число: где-то около миллиона векторов, но конкретная граница гуляет в зависимости от размерности эмбеддингов, требуемого QPS, доступной RAM, сложности фильтров и целевого recall. Ниже этого масштаба встроенного обычно хватает; выше — стоит смотреть предметно, по своей нагрузке. Что происходит с pgvector на больших объёмах и как выжать из него больше: pgvector вглубьСкоро.
Когда нужна выделенная
Набор условий, при котором стоит смотреть в сторону выделенной базы, обычно такой: миллионы и больше векторов; гибридный поиск (смысл вперемешку с ключевыми словами); сложная фильтрация без заметного недобора (recall); требования к throughput и SLA. В этих сценариях выделенные движки вроде Qdrant, Milvus или Weaviate дают более специализированные механики эксплуатации, фильтрации, гибридного поиска и масштабирования.
Важно, что дело не в «умеет / не умеет»: встроенные решения тоже делают векторный поиск — pgvector поддерживает и точный, и приблизительный поиск, косинусное расстояние <=>, JOIN и всё остальное из Postgres; Redis и OpenSearch — тоже. Разница в том, насколько глубоко эти механики проработаны под нагрузку. И компромиссы никуда не деваются — фильтрация в ANN всё равно имеет свою цену, — просто в выделенном движке она управляется аккуратнее.
Разбор самих движков: Qdrant, Milvus, WeaviateСкоро. А выбор «pgvector или выделенная база» как отдельное инженерное решение, со своими критериями: pgvector или выделенная базаСкоро.
Ступени этой лестницы проходят снизу вверх, а не наоборот: начинать с выделенной базы ради десяти тысяч документов значит платить за проблему, которой нет.
Типичные ошибки — они же «когда не нужны»
За разбором лестницы выбора стоит несколько ошибок, которые на практике встречаются чаще прочих.
Выбор базы раньше, чем понятны объём данных и паттерн запросов. Правильный порядок — сначала посчитать, сколько объектов предстоит хранить, как часто и какими запросами их ищут, и только потом выбирать инструмент под эту нагрузку. Выбор в обратном порядке — сначала модная база, потом попытка подогнать под неё задачу — почти всегда добавляет сложности без пользы.
Игнор качества эмбеддингов. Если модель подобрана небрежно или векторы посчитаны не для того языка и домена, никакой индекс — ни HNSW, ни IVF, ни самый точный ANN-алгоритм — не вытащит смысл, которого в векторах нет. Мусор на входе даёт мусор на выходе, и для векторного поиска это особенно верно: качество поиска ограничено сверху качеством эмбеддингов, а не настройками индекса.
Отсутствие метрик качества поиска. «Вроде находит нужное» — это впечатление, а не метрика. Векторный поиск — это поиск с ранжированием, и меряют его соответствующими метриками: Recall@K и Precision@K (сколько релевантного попало в топ-K результатов), а если важен порядок выдачи — ещё MRR или nDCG. Без них нельзя сравнить два индекса, две модели эмбеддингов или два порога приближённости между собой, и тем более — заметить, что качество поиска потихоньку деградирует. Как устроить измерение и мониторинг этих метрик на практике: карта выбора и мониторинг recallСкоро.
Переусложнение. Поднять отдельный кластер Milvus ради десяти тысяч документов — значит добавить в инфраструктуру новый stateful-компонент, новый цикл эксплуатации и новую точку отказа там, где pgvector в уже существующем PostgreSQL закрыл бы задачу без единой новой сущности в стеке.
Отдельно от этих ошибок стоят два вопроса, которые здесь сознательно не разбираются, а вынесены в отдельные статьи серии: как совмещать векторный поиск с поиском по ключевым словам — гибридный поиск и rerankingСкоро — и как фильтровать по атрибутам, не теряя точность ANN-поиска — фильтрация и консистентность в ANNСкоро.
Куда дальше
В retrieval-augmented generation (RAG) модель отвечает не по памяти, а по фрагментам текста, которые ей подложили в контекст, — и находит эти фрагменты именно векторный поиск. Насколько точно он находит нужное, настолько же точным будет и итоговый ответ: качество поиска — это потолок качества всей цепочки RAG. Если нужный факт не попал в найденный контекст, ни промпт, ни более крупная модель не смогут надёжно подставить его как обоснованный (grounded) ответ — в лучшем случае угадают, в худшем придумают. Как устроена эта цепочка целиком: RAG end-to-end: от эмбеддингов до ответаСкоро.
Дальше в серии каждый слой из этой статьи планируется разобрать отдельно и вглубь — статьи готовятся следом за этой вводной:
- ANN вглубь: HNSW, IVF, PQСкоро — как устроены индексы приблизительного поиска;
- pgvector вглубьСкоро — что делать, когда pgvector нужно выжать по максимуму;
- Qdrant, Milvus, WeaviateСкоро — разбор выделенных движков;
- гибридный поиск и rerankingСкоро — совмещение смысла и ключевых слов;
- фильтрация и консистентность в ANNСкоро — атрибутивные фильтры и их цена для recall;
- pgvector или выделенная базаСкоро — карта выбора и эксплуатация в проде.
Когда серия выйдет, для тех, кому решение нужно здесь и сейчас, а не после чтения всего, удобной точкой входа будет последняя статья — карта выбора: там лестница из этой вводной собрана в практический вид. Пока продолжения готовятся, ссылки выше помечены как ожидаемые.
Документация и первоисточники
- pgvector — векторный поиск внутри PostgreSQL
- Qdrant — документация выделенного движка
- Milvus — документация выделенного движка
- Weaviate: поиск — векторный и гибридный поиск в Weaviate
- OpenSearch k-NN — векторный поиск в поисковом движке
- Redis Vector Search — векторные запросы в Redis
- HNSW — оригинальная статья — алгоритм приблизительного поиска, лежащий в основе большинства индексов
Комментарии