Как вы управляете cost хранения векторной БД при миллиарде векторов?

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

Управление стоимостью хранения векторной БД при масштабе миллиарда векторов требует комбинации сжатия векторов (например, Product Quantization (PQ)) и tiered storage (многоуровневого хранения) с автоматическим перемещением данных между горячим (SSD), тёплым (NVMe) и холодным (S3) слоями. Ключевые техники — PQ (сжатие до 1/8 исходного размера) и использование DiskANN в качестве разреженного индекса для холодных данных. Такой подход позволяет снизить затраты на хранение на 80–90% без существенной потери качества поиска (recall падает на 1–3%).


1. Проблема: стоимость хранения миллиарда векторов

Вектор эмбеддинга (обычно float32, размерность 768–1536) занимает от 3 КБ до 6 КБ. Для миллиарда векторов:

  • Размерность 768 × 4 байта = 3072 байта ≈ 3 КБ на вектор.
  • Итого: 1e9 × 3 КБ ≈ 3 ТБ без индекса.
  • С учётом индекса (IVF, HNSW) и метаданных — 5–10 ТБ.

Хранение такого объёма на быстрых SSD (например, NVMe) обходится дорого. Основные драйверы cost:

  • Ёмкость (GB/TB);
  • IOPS и latency (быстрое хранилище стоит дороже);
  • Репликация для отказоустойчивости;
  • Резервное копирование.

Цель: минимизировать cost при сохранении требуемого recall@k и latency.


2. Product Quantization (PQ) – основное сжатие

Product Quantization — метод сжатия векторов путём их разбиения на подпространства и квантования каждого подпространства отдельным кодбуком. Результат: каждый вектор заменяется компактным кодом (обычно 8–32 бита на подпространство). Сжатие в 8–16 раз.

Как работает PQ:

  1. Делим вектор размерности D на M подпространств (например, M=8, каждое размерностью D/M).
  2. Для каждого подпространства обучаем кодбук из k центроидов (обычно k=256 → 8 бит).
  3. Каждый вектор квантуется: для каждого подпространства записывается номер ближайшего центроида.
  4. Итоговый код — M чисел по 8 бит = M байт. Для M=8 это 8 байт вместо 768×4=3072 байт (сжатие в 384 раза).

На практике используют OPQ (Optimized Product Quantization) для улучшения качества.

Trade-off: чем сильнее сжатие, тем ниже точность поиска. Обычно выбирают M так, чтобы код был 32–64 байта (сжатие в 50–100 раз), что даёт падение recall на 1–3% при правильной настройке.

Применение в индексах: PQ используется в IVF+PQ (Faiss) и DiskANN (Microsoft). В DiskANN векторы хранятся сжатыми, а при поиске вычисляется приблизительное расстояние через кодбуки.

Пример конфигурации Faiss:

import faiss

dim = 768
m = 16  # количество подпространств
nbits = 8  # бит на подпространство
pq = faiss.ProductQuantizer(dim, m, nbits)
# Обучаем на выборке векторов
pq.train(x_train)
# Кодируем
codes = pq.compute_codes(x)
# Декодируем (с потерями)
x_decoded = pq.decode(codes)

Экономия: 1 млрд векторов размерности 768 → без сжатия: 3 ТБ. С PQ (m=16, 16 байт на вектор) → 16 ГБ (в 188 раз меньше). Даже с overhead индекса — экономия колоссальная.


3. Tiered storage (многоуровневое хранение)

Второй ключевой приём — разделение данных по слоям в зависимости от частоты доступа:

УровеньХранилищеТипичный размер векторовLatencyCost за GB
HotNVMe SSD / RAM (in-memory)Последние 3 месяца (10–20% данных)<1 msВысокий
WarmNVMe SSD / SATA SSD3–12 месяцев (30–40% данных)1–10 msСредний
ColdS3 / HDD / Tape>12 месяцев (остальное)10–100 msНизкий

Механизм перемещения:

  • Автоматическая политика на основе времени последнего доступа (LRU) или метаданных документа (дата создания).
  • Для hot-слоя используется быстрый индекс (HNSW, IVF) без сжатия или с низким сжатием.
  • Для cold-слоя — DiskANN или IVF+PQ с высоким сжатием, данные на S3.

DiskANN — библиотека от Microsoft, оптимизированная для SSD и разреженных графов. Она хранит сжатые векторы (PQ) и граф на диске, при поиске подгружает только необходимые страницы. Позволяет работать с данными на S3 с приемлемой latency (10–50 ms) за счёт prefetch и кэширования.

Пример архитектуры:

Hot (NVMe, 200 млн векторов, HNSW+float32)
    |
    | автоматическая выгрузка по возрасту
    v
Warm (SSD, 400 млн, IVF+PQ с factor 8)
    |
    | выгрузка после [[12. Как вы фильтруете документы по метаданным в векторной БД\|12]] мес
    v
Cold (S3, 400 млн, DiskANN с PQ factor 32, граф на SSD/NVMe кэш)

4. DiskANN – ключевая технология для cold tier

DiskANN (Disk-based Approximate Nearest Neighbor) сочетает:

  • PQ сжатие для хранения векторов;
  • Vamana граф (разреженный, построенный так, чтобы минимизировать дисковые чтения);
  • Beam search с параллельной загрузкой страниц.

Особенности:

  • Индекс строится один раз, затем только обновляется (поддерживает вставки/удаления).
  • При поиске загружает со S3 только необходимые страницы графа и сжатые векторы.
  • Recall@k при 1 млрд векторов: 95–98% при latency 5–20 ms (с S3 через CDN).

Сравнение с in-memory индексами:

ПараметрIn-memory (HNSW)DiskANN (cold tier)
RAM~10 ТБ (1e9 floats)~100 ГБ (кэш + кодбуки)
StorageSSD/NVMeS3
Latency<1 ms5–50 ms
Cost ($/GB/мес)~0.20 (NVMe)0.023 (S3 Standard)
Recall99%+95–98%

Вывод: DiskANN позволяет хранить холодные данные на дешёвом S3, жертвуя 1–3% recall ради 90% экономии.


5. Дополнительные методы снижения cost

5.1 Снижение размерности эмбеддингов

  • Использование моделей с меньшей размерностью (например, text-embedding-3-small от OpenAI – 512 вместо 1536) снижает объём в 3 раза.
  • PCA или обучение мелких эмбеддингов (distillation) – даёт дополнительные 20–40% сжатия.

5.2 Sparsification (разреживание)

  • Замена плотных float32 на binary (1 бит на компоненту) – сжатие в 32 раза, но падение recall.
  • Binary quantization с расстоянием Хэмминга – быстро, дешево, но только для сценариев с высокой toleration к ошибкам.

5.3 Удаление дубликатов и устаревших векторов

  • Deduplication на основе эмбеддингов или хэшей (LSH) – сокращает объём на 10–30%.
  • TTL (time-to-live) для временных данных – автоматическое удаление.

5.4 Компрессия метаданных

  • Метаданные (текст, ID, таймстемпы) можно хранить в Parquet с colunar compression (snappy) или zstd – экономия 2–4x.

6. Влияние сжатия на качество поиска

Необходимо найти баланс между cost и recall. Пример bбенчмарка при 100 млн векторов (размерность 768):

МетодРазмер (GB)Recall@10Latency (ms)Cost/мес ($, 1e9 векторов)
float32 + HNSW30799.5%1~60,000
IVF+PQ (M=32)3298.2%5~6,500
DiskANN (M=16)1697.0%15~3,200 (cold tier S3)
Binary (1 bit)0.7585.0%0.5~150

Рекомендация: для hot tier использовать float32 или IVF+PQ с низким сжатием (M=4), для warm – IVF+PQ с M=16, для cold – DiskANN с M=32.


7. Автоматизация перемещения данных (tiering policy)

Инструменты:

  • Kubernetes + Argo Workflows для оркестрации batch-задач.
  • Custom scheduler на основе Python + boto3 для S3.
  • Векторные БД с поддержкой tiering: например, Milvus (поддержка multi-tier storage), Qdrant (плагины S3).

Простая политика:

  • Новые векторы попадают в hot tier.
  • После 30 дней без обращений – перемещаются в warm.
  • После 6 месяцев – в cold (с перестроением индекса в DiskANN).
  • При запросе к cold – временно кэшируются в hot tier (LRU).

Мониторинг:


8. Сравнение total cost of ownership (TCO)

Рассчитаем TCO для 1 млрд векторов (768d) на AWS (цены 2025):

КомпонентВариант 1: всё in-memory (NVMe)Вариант 2: multi-tier с PQЭкономия
Storage (NVMe gp3)100 TB × 0.08 $/GB/мес = 8000 $20 TB (hot+warm) × 0.08 = 1600 $ + 10 TB (S3 cold) × 0.023 = 230 $~77%
Compute (EC2)20 × r7gd.16xlarge = ~15,000 $10 × r7gd.8xlarge + 5 × c7g.4xlarge (DiskANN) = ~8,500 $~43%
Data transfer~500 $~1,000 $ (S3 запросы)+
Total~23,500 $/мес~10,330 $/мес~56%

Вывод: multi-tier с PQ и DiskANN даёт экономию 50–60% при сохранении приемлемого качества (recall 97%+).


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

Задача: Спроектировать прототип минимальной векторной БД для 10 млн векторов с tiered storage на AWS (или локально с эмуляцией S3 через MinIO).

Инструменты: Python, FAISS, boto3, MinIO (local S3), pandas, numpy.

Шаги:

  1. Сгенерировать 10 млн случайных векторов размерности 768 (float32).
  2. Разделить их на 3 группы по времени (имитация: первые 7 млн – старые, 2 млн – средние, 1 млн – новые).
  3. Построить индекс для новых (hot): HNSW (FAISS), хранить в оперативной памяти.
  4. Для средних: IVF+PQ (m=8), сохранить на локальный SSD.
  5. Для старых: обучить PQ (m=16) и построить DiskANN-подобный граф (можно использовать lightweight реализацию DiskANN в FAISSfaiss.IndexIVFPQ с use_float16=False и mmap).
  6. Реализовать search: при запросе сначала искать в hot, затем в warm (с fallback), затем в cold. Возвращать top-k из всех.
  7. Измерить recall@10 и latency для каждого слоя.
  8. Подсчитать условную стоимость (ёмкость в GB × цена AWS).

Ожидаемый результат: Рабочий скрипт, который демонстрирует, что cold-tier с PQ и mmap на SSD даёт recall 95%+ при ~10x экономии памяти.

Расширение: Добавить автоматический перенос данных между слоями по возрасту (хранить метаданные в SQLite).


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

ВопросТема
265Выбор векторной БД для масштаба
266Компрессия эмбеддингов (quantization)
268Пайплайн синхронизации данных
272Мониторинг производительности векторной БД
273Cost оптимизация inference
278Стратегии партиционирования (sharding)

Навигация