Logo Craft Homelab Docs Контакты Telegram
Векторные базы данных — Pinecone, Weaviate, Qdrant
Sat Jan 03 2026

Векторные базы данных: полное руководство

Векторные базы данных — это не просто еще один хранилище данных. Это специализированные движки для семантического поиска, где каждый выбор индекса, квантования или архитектуры напрямую влияет на latency, стоимость и способность вашей RAG-системы работать с миллионами векторов в реальном времени. Забудьте про “универсальные решения”: здесь каждая технология делает ставки на конкретные сценарии, а их trade-offs определяют, выдержит ли ваша архитектура нагрузку.

Технический вызов: ANN-поиск при миллионах векторов и динамических обновлениях

Когда вы сталкиваетесь с поиском ближайших соседей (ANN) в высокомерном пространстве, сталкиваетесь с фундаментальным конфликтом: как сохранить приемлемую latency при постоянных upsert/delete-операциях? Классические индексы (KD-Tree, VP-Tree) ломаются на >10K векторов. HNSW (Hierarchical Navigable Small World) решает это, но его эффективность зависит от баланса между связностью (m), глубиной поиска (ef) и стратегией квантования. Проблема усугубляется, если вам нужно фильтровать по метаданным — каждый дополнительный слой логики увеличивает latency. Решение: архитектура, которая интегрирует фильтрацию в обход графа, или компромисс через гибридный поиск.

Pinecone (managed SaaS)

Pinecone берет на себя всю DevOps-болезнь, но платит за это ценой контроля. Его ядро — кастомный HNSW, где ef динамически подстраивается под качество early-results. Это умно, но черный ящик: вы не можете тонко настроить поведение. Ключевая оптимизация — Product Quantization (PQ): векторы сжимаются в 8-битные кодбуки, уменьшая индекс в 4-8×. Но это требует оффлайн-тренировки на репрезентативной данных, а обновления проходят через WAL с фоновым мерджем. При массовых записях возможны пики latency из-за фрагментации графа.

Trade-offs: Vendor lock-in, линейный рост стоимости при >100M векторов, ограниченные метрики (нет Manhattan distance). Идеально для стартапов, где скорость важнее контроля, но осторожно с масштабом — стоимость RU/WU может сорвать бюджет.

Weaviate (open-source + облачный)

Weaviate разделяет векторы и метаданные (LSM-дерево + файлы), упрощая работу с payload. Гибридный поиск (HNSW + inverted index) позволяет совмещать векторные запросы с BM25, но inverted index обновляется пост-фактум. Добавляет 10-30% latency и гонки при фильтрации сразу после upsert. Мета-модель (GraphQL) позволяет добавлять кастомные vectorizers, но каждый вызов — дополнительная CPU-нагрузка на ноде. Холодный старт 2-5 минут при большом числе модулей.

Trade-offs: Гибкость за счет latency, ручное шардирование, задержки обновления индекса. Выбирайте, если критичен гибридный поиск векторов и текста, но будьте готовы к компромиссам в производительности.

Qdrant (open-source, Rust)

Rust дает предсказуемую производительность без UB, но главное отличие — фильтрация, встроенная в обход HNSW. При traversal графа проверяются условия фильтра (hash/tree индексы) до вычисления расстояния. Это экономит 50% CPU при жестких фильтрах. On-disk quantization mmap’ит сегменты графа, позволяя работать с датасетом, превышающим RAM (деквантование добавляет 5-10% CPU). Архитектура single-binary с RAFT-репликацией: лидер обрабатывает writes, followers — reads. Простой в развертывании, но лидер становится bottleneck при high upsert-rate.

Trade-offs: Линейный рост RAM от индексов (уникальные значения полей), нет GPU-ускорения. Оптимален для сценариев с жесткими фильтрами (персонализация, временные окна).

Milvus (корпоративная / облачная)

Распределенная платформа: etcd (метаданные), MinIO (сжатые векторы), Pulsar (лог), query/data nodes. Индекс-билдер поддерживает IVF-PQ, HNSW, DiskANN. IVF-PQ делит пространство на ячейки (Voronoi), каждая квантуется независимо — эффективно при >100M векторов, но чувствителен к сдвигу данных. Data nodes хранят векторы в MinIO, query nodes — в RAM. Вводит сетевую латентность 1-5 мс между нодами.

Trade-offs: Избыточный оверхед для <10M векторов, сложная отладка, необходимость K8s-инженера. Для корпоративных нагрузок >10K QPS.

Пример кода: Qdrant

# Клиент с пулом и таймаутом — must-have под нагрузкой
from qdrant_client import QdrantClient
from qdrant_client.http.models import VectorParams, Distance, OptimizersConfigDiff, HnswConfigDiff

client = QdrantClient(
    host="localhost",
    port=6333,
    timeout=10,          # Защита от зависаний
    prefer_grpc=True,    # gRPC быстрее при большом трафике
)

# Баланс качества и RAM: m=16 (средняя связность), ef_construct=200 (качество построения)
COLL = "rag_docs"
if not client.collection_exists(COLL):
    client.recreate_collection(
        collection_name=COLL,
        vectors_config=VectorParams(size=768, distance=Distance.COSINE),
        hnsw_config=HnswConfigDiff(m=16, ef_construct=200),
        on_disk_payload=True,   # Индексы payload на диске → экономия RAM
        optimizers_config=OptimizersConfigDiff(max_segment_size=50_000),
    )

# Формируем точки: вектор + легкий payload. Текст хранится отдельно (S3/MinIO)
points = [
    {
        "id": i,
        "vector": emb.tolist(),
        "payload": {
            "doc_id": f"doc_{i}",
            "source": "wiki",
            "category": "science",   # Индексируем только низкокардинальные поля
        },
    }
    for i, emb in enumerate(embeddings)
]

# Пакетный upsert: размер подбираем под MTU, избегая TCP-фрагментации
BATCH = 256
for i in range(0, len(points), BATCH):
    client.upsert(
        collection_name=COLL,
        points=points[i:i+BATCH],
        wait=True,   # Гарантирует репликацию перед возвратом
    )

# Фильтрация во время обхода графа — экономия CPU
res = client.search(
    collection_name=COLL,
    query_vector=query_emb.tolist(),
    limit=10,
    with_payload=True,
    query_filter={"must": [{"key": "category", "match": {"value": "science"}}]},
    params={"ef": 120},   # Эмпирический recall~0.92 для наших данных
)

Неочевидные детали:

  • m * N * 8 байт — RAM под граф HNSW (при 10M векторов и m=16 ~1.3 GB).
  • on_disk_payload=True выносит индексы payload на диск, но граф остается в RAM.
  • Фильтр проверяется во время traversal — пост-фильтрация в Python избыточна.
  • wait=True упрощает синхронные пайплайны; для async — отслеживайте _recovery.

Узкие места в продакшене

  • Pinecone: Нелинейный рост стоимости при >100M векторов. Архивация в S3 снижает расходы, но усложняет операции и риски staleness.
  • Weaviate: Холодный старт 2-5 минут. Inverted index обновляется с задержкой → гонки при фильтрации сразу после upsert.
  • Qdrant: Линейный рост RAM от индексов (поле user_id с 1M уникальных значений съест >10 GB).
  • Milvus: Сетевые хопы между query/data nodes добавляют 1-5 мс latency. Отладка требует агрегации логов из 4+ сервисов.

Вывод: когда что использовать

  • Pinecone: MVP и стартапы с ограниченным бюджетом ($0.20-$0.50 за 1M векторов/мес). Zero-Ops, но осторожно с масштабом >1B векторов.
  • Weaviate: Гибридный поиск (вектор + BM25) + встроенные vectorizers. Готовьтесь к 20-30% latency и ручному шардированию.
  • Qdrant: Жесткие фильтры, персонализация, экономия RAM. Один бинарник, но контролируйте индексы полей.
  • Milvus: Корпоративные нагрузки >10K QPS. Только если есть SRE для K8s. Для <10M векторов используйте Milvus Lite.

Бонус: Замеряйте recall@k на реальном трафике, а не на бенчмарках. Оптимальное ef или nprobe — это recall~0.9, а не 0.99: последнее экспоненциально увеличивает latency. Помните, что ANN — это всегда компромисс между памятью, скоростью и точностью.