Как вы проектируете векторную БД с миллиардом векторов при ограниченном бюджете?

Краткий тезис

Проектирование векторной БД на миллиард векторов с ограниченным бюджетом требует отказа от дорогих in-memory решений в пользу гибридных подходов: DiskANN (векторы на NVMe, индексы в памяти), Product Quantization (PQ) для сжатия векторов, tiered storage (горячие данные в RAM, остальное на диске) и pruning нерелевантных векторов. При бюджете ~$500/месяц можно собрать self-hosted сервер (4×2TB NVMe, 64GB RAM) и обслуживать 1B векторов размерности 768 с latency <50ms.


1. Оценка требований и ограничений

Прежде чем выбирать архитектуру, нужно понять параметры нагрузки:

  • Размерность векторов: обычно 768 (text-embedding-3-small) или 1024 (Ada-002). Чем выше размерность, тем больше памяти и диска.
  • Количество векторов: 1 млрд.
  • Latency: для RAG обычно приемлемо 10–100 мс на поиск.
  • Throughput: сколько запросов в секунду (QPS). Для стартапа может быть 10–100 QPS.
  • Бюджет: $500/месяц — это ~$6000/год, что исключает managed облачные сервисы (Pinecone, Weaviate Cloud) для такого объёма.

Термин: Self-hosted — развёртывание на собственном железе или VPS, без managed сервисов.


2. DiskANN: основа для миллиарда векторов

DiskANN (Microsoft Research) — алгоритм приближённого поиска ближайших соседей (ANN), оптимизированный для хранения векторов на SSD/NVMe, а индекса — в RAM.

  • Принцип: строит граф (Vamana), где вершины — векторы. Граф хранится на диске, но «горячие» узлы кэшируются в RAM.
  • Память: для 1B векторов (768 dim) индекс Vamana занимает ~10–15 GB RAM (зависит от параметров). Сами векторы на диске — ~3 TB (1B × 768 × 4 байта = 3.07 TB).
  • Latency: ~5–20 мс на NVMe SSD.
  • Бюджет: дешёвые NVMe диски (2TB ~ $100–150), RAM 64GB ~ $200.

Термин: ANN (Approximate Nearest Neighbors) — поиск не точных, а приближённых ближайших соседей, с жертвой точности ради скорости и памяти.


3. Product Quantization (PQ) для сжатия векторов

Product Quantization — метод сжатия векторов путём разбиения на подвекторы и квантования каждого подвектора в центроид из кодовой книги.

  • Стандарт: 4 бита на подвектор (16 центроидов). Для 768 dim и 96 подвекторов (по 8 dim) получаем 96 × 4 бита = 48 байт на вектор вместо 3072 байт (float32).
  • Результат: 1B векторов занимают ~48 GB диска (вместо 3 TB).
  • Потеря точности: recall@10 может упасть на 1–5% в зависимости от настройки.
  • Совместимость: DiskANN поддерживает PQ — векторы хранятся сжатыми, а при поиске расстояния считаются по квантованным представлениям.

Термин: Кодовая книга (codebook) — набор центроидов, полученных кластеризацией (k-means) на обучающей выборке подвекторов.


4. Tiered storage: горячие, тёплые и холодные данные

Не все векторы одинаково часто запрашиваются. Tiered storage позволяет держать в RAM только самые популярные.

  • Hot tier (1% векторов, ~10M): HNSW-индекс в RAM. Latency <1 мс.
  • Warm tier (10–20%): DiskANN с кэшированием часто посещаемых узлов.
  • Cold tier (остальные): DiskANN с полным чтением с диска, latency ~20–50 мс.

Как определить hot set: по логам retrieval — векторы, которые никогда не ретривятся (pruning), можно удалить или переместить в cold.

Термин: HNSW (Hierarchical Navigable Small World) — графовый алгоритм ANN, очень быстрый в RAM, но требует ~2× больше памяти, чем DiskANN.


5. Pruning: удаление нерелевантных векторов

Анализ логов retrieval за месяц показывает, что многие векторы никогда не возвращаются в top-k. Их можно удалить или архивировать.

  • Метод: логируем ID всех векторов, попавших в результаты хотя бы раз за N дней. Остальные помечаем как «мёртвые».
  • Эффект: можно сократить объём на 30–70% без потери качества (если данные избыточны).
  • Риск: для редких запросов может не найтись релевантных документов. Нужен fallback — полный поиск по архиву при низком confidence.

Термин: Confidence score — оценка релевантности (например, косинусное расстояние). Если все результаты ниже порога, можно запустить полный поиск.


6. Бюджет $500/месяц: железо и развёртывание

Self-hosted сервер на dedicated или аренда VPS:

КомпонентМодельЦена (мес)
CPUAMD EPYC 8 ядер$50
RAM64 GB DDR4$80
NVMe4×2 TB (8 TB)$200
Сеть1 Gbps$30
ОС/ПОUbuntu + DiskANN (open source)$0
Итого$360

Остаток $140 на резервное копирование, мониторинг, неожиданные расходы.

Важно: DiskANN — open source (реализация от Microsoft), можно собрать и настроить. Альтернатива — FAISS с IVF+PQ, но FAISS менее эффективен для дискового хранения.


7. Сравнение подходов для 1B векторов (768 dim)

ПодходRAMДискLatencyRecall@10Бюджет/мес
HNSW (всё в RAM)~600 GB3 TB<1 ms0.99$3000+
DiskANN (без PQ)15 GB3 TB10 ms0.95$400
DiskANN + PQ (4-bit)15 GB48 GB15 ms0.92$360
FAISS IVF+PQ (на диске)10 GB50 GB30 ms0.90$350

Вывод: DiskANN + PQ — оптимальный баланс для ограниченного бюджета.


8. Дополнительные оптимизации

  • Batching: группировка запросов для уменьшения накладных расходов на I/O.
  • Кэширование результатов: частые запросы (например, «что такое RAG») можно кэшировать в Redis.
  • Асинхронная запись: новые векторы добавляются батчами, а не по одному, чтобы не фрагментировать граф.
  • Мониторинг: Prometheus + Grafana для отслеживания latency, hit rate, использования диска.

Термин: Фрагментация графа — при частых вставках граф DiskANN может деградировать, требуется периодическая перестройка (rebuild).


9. Пример кода: инициализация DiskANN с PQ

# Псевдокод для DiskANN (библиотека diskannpy)
import diskannpy as dap

# Параметры
index_path = "/mnt/nvme/diskann_index"
data = load_vectors("vectors.bin")  # 1B x 768 float32

# Создание индекса с PQ (4-bit)
dap.build_memory_index(
    data=data,
    distance_metric="l2",
    index_path=index_path,
    complexity=100,          # параметр Vamana
    graph_degree=64,
    pq_bits=4,               # 4 бита на подвектор
    num_pq_chunks=96         # 768 / 8 = 96
)

# Поиск
query = np.random.rand(768).astype(np.float32)
result = dap.query(
    index_path=index_path,
    query=query,
    k=10,
    search_radius=0.3
)
print(result.ids, result.distances)

10. Мониторинг и итерации

После развёртывания нужно измерять:

  • Hit rate (доля запросов, где найден хотя бы один релевантный документ).
  • Latency p99 — 99-й перцентиль времени поиска.
  • Disk usage — рост индекса.
  • Recall на тестовом датасете — раз в неделю прогонять бенчмарк.

Если recall падает ниже 0.9, можно увеличить search_radius или перестроить индекс с более точными параметрами.


Пет-проект для закрепления

Задача: Развернуть векторную БД на 10 млн синтетических векторов (768 dim) на одной машине с 16 GB RAM и 500 GB SSD, имитируя ограниченный бюджет.

Инструменты: Python, diskannpy (или FAISS), Docker, Prometheus + Grafana.

Шаги:

  1. Сгенерировать 10M случайных векторов и сохранить в бинарный файл.
  2. Установить diskannpy и построить индекс с PQ (4-bit).
  3. Написать скрипт для поиска (1000 запросов) и замерить latency.
  4. Добавить мониторинг: время ответа, использование RAM/диска.
  5. Сравнить с HNSW (in-memory) — увидеть разницу в памяти и скорости.

Ожидаемый результат: Работающая векторная БД с latency <20 мс, потреблением RAM <4 GB, диска <500 MB (с PQ). Поймёте trade-offs между точностью и ресурсами.


Связь с другими вопросами

ВопросТема
530Как вы выбираете эмбеддинг-модель для RAG?
531Как вы оцениваете качество retrieval?
532Какие стратегии chunking вы знаете?
534Как вы обновляете документы в существующей RAG-системе?
536Как вы уменьшаете latency RAG-системы?
540Что такое Self-RAG и когда его использовать?

Навигация