Суть
После чанкинга и эмбеддинга векторы надо где-то хранить и быстро искать по косинусной близости. «Зашвыриваем чанки и их эмбеддинги в базу, а на запрос она строит вектор запроса и ищет похожие». Разные БД оптимизированы под разные сценарии.
Зачем это нужно
Линейный перебор миллионов векторов нереален в реальном времени — нужны специальные ANN-индексы. И когда корпус растёт от тысяч до сотен миллионов векторов, «лёгкое» решение перестаёт держать нагрузку.
Как работает (сравнение)
| БД | Масштаб | Сильная сторона |
|---|---|---|
| Milvus | >100M, K8s | Лучшее масштабирование, RRF из коробки |
| Qdrant | >100M, <5 мс | Лучшая фильтрация по метаданным |
| PostgreSQL / pgvector (Supabase) | ≤~1M уверенно (до ~10M с тюнингом) | «Развёрнут везде», высокая доступность; удобно когда embeddings рядом с relational data |
| Aerospike | >1B | Самая быстрая по скорости |
| FAISS (Meta) | in-memory | Библиотека для поиска в памяти, прототип |
| Chroma | in-memory + persist | Лёгкая, сохранение индекса на диск |
| Weaviate | — | Ещё один популярный вариант |
- Для прототипа — FAISS и Chroma «два самых простых начальных решения»: работают в оперативной памяти, минимум настройки.
- Для продакшена — специализированные лидеры; Qdrant можно поднять как облачный сервис и стучаться по сети.
- Embedding-модель и БД должны быть согласованы (одна модель эмбеддингов для совместимости, см. Vector Store Persistence).
- Выбор калибруют по бенчмаркам: ann-benchmarks.com, superlinked vector-db-comparison, MERA (для русского).
- Потолок pgvector (осторожно, не универсальный закон): уверенно подходит для малых/средних корпусов, особенно когда embeddings живут рядом с relational data; комфортный ориентир — до ~1M векторов, до ~10M возможно с тюнингом и компромиссами по index build / памяти / recall. Порог 50M не использовать как дефолт без собственного бенчмарка. Для сложной фильтрации, hybrid/BM25/sparse, multivector и больших индексов чаще нужен dedicated store (Qdrant/Milvus). ⚠️ Строгие числа — из источника Qdrant (vendor-bias).
- Когда pgvector достаточно (желательно все условия сразу): ≤~1M векторов; нет селективной фильтрации по метаданным (tenant/category); не нужен hybrid/BM25; векторы — атрибут relational-строки. Иначе → dedicated. Qdrant: filterable HNSW (pre-filter по метаданным), нативный BM25 через sparse-векторы, multivector. Ловушка ColBERT: эмбеддинг на каждый токен → 100k документов = 10M+ векторов (за пределами pgvector).
Пример
На этапе прототипа БД взаимозаменяемы: один embedding-модель и единый API from_documents / similarity_search поверх Chroma, Qdrant и FAISS in-memory.
vs_chroma = Chroma.from_documents(chunks, embedding=embeddings, collection_name="demo")
vs_qdrant = QdrantVectorStore.from_documents(chunks, embedding=embeddings,
location=":memory:", collection_name="demo")
vs_faiss = FAISS.from_documents(chunks, embedding=embeddings)
def retrieve(vs, query, k=2): # БД меняется, retrieval-код — нет
return vs.similarity_search(query, k=k)
Связано с
- RAG — векторная БД = хранилище retrieval-слоя
- Embeddings — что именно хранится в базе
- Vector Store Persistence — как сохранять и переносить индексы между машинами
- Agent Memory — long-term память агента реализуется на vector DB
Открытые вопросы
- Qdrant vs Milvus на проде с русскоязычным корпусом и фильтрацией