中文翻译暂不可用,显示俄语原文。
Как вы управляете 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:
- Делим вектор размерности D на M подпространств (например, M=8, каждое размерностью D/M).
- Для каждого подпространства обучаем кодбук из k центроидов (обычно k=256 → 8 бит).
- Каждый вектор квантуется: для каждого подпространства записывается номер ближайшего центроида.
- Итоговый код — 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 (многоуровневое хранение)
Второй ключевой приём — разделение данных по слоям в зависимости от частоты доступа:
| Уровень | Хранилище | Типичный размер векторов | Latency | Cost за GB |
|---|---|---|---|---|
| Hot | NVMe SSD / RAM (in-memory) | Последние 3 месяца (10–20% данных) | <1 ms | Высокий |
| Warm | NVMe SSD / SATA SSD | 3–12 месяцев (30–40% данных) | 1–10 ms | Средний |
| Cold | S3 / 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 ГБ (кэш + кодбуки) |
| Storage | SSD/NVMe | S3 |
| Latency | <1 ms | 5–50 ms |
| Cost ($/GB/мес) | ~0.20 (NVMe) | 0.023 (S3 Standard) |
| Recall | 99%+ | 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@10 | Latency (ms) | Cost/мес ($, 1e9 векторов) |
|---|---|---|---|---|
| float32 + HNSW | 307 | 99.5% | 1 | ~60,000 |
| IVF+PQ (M=32) | 32 | 98.2% | 5 | ~6,500 |
| DiskANN (M=16) | 16 | 97.0% | 15 | ~3,200 (cold tier S3) |
| Binary (1 bit) | 0.75 | 85.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).
Мониторинг:
- Сбор метрик: размер по tiers, частота обращений, latency p99.
- CloudWatch / Prometheus + Grafana.
- Alert при превышении бюджета.
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.
Шаги:
- Сгенерировать 10 млн случайных векторов размерности 768 (float32).
- Разделить их на 3 группы по времени (имитация: первые 7 млн – старые, 2 млн – средние, 1 млн – новые).
- Построить индекс для новых (hot): HNSW (FAISS), хранить в оперативной памяти.
- Для средних: IVF+PQ (m=8), сохранить на локальный SSD.
- Для старых: обучить PQ (m=16) и построить DiskANN-подобный граф (можно использовать lightweight реализацию DiskANN в FAISS –
faiss.IndexIVFPQсuse_float16=Falseиmmap). - Реализовать search: при запросе сначала искать в hot, затем в warm (с fallback), затем в cold. Возвращать top-k из всех.
- Измерить recall@10 и latency для каждого слоя.
- Подсчитать условную стоимость (ёмкость в GB × цена AWS).
Ожидаемый результат: Рабочий скрипт, который демонстрирует, что cold-tier с PQ и mmap на SSD даёт recall 95%+ при ~10x экономии памяти.
Расширение: Добавить автоматический перенос данных между слоями по возрасту (хранить метаданные в SQLite).
Связь с другими вопросами
| Вопрос | Тема |
|---|---|
| 265 | Выбор векторной БД для масштаба |
| 266 | Компрессия эмбеддингов (quantization) |
| 268 | Пайплайн синхронизации данных |
| 272 | Мониторинг производительности векторной БД |
| 273 | Cost оптимизация inference |
| 278 | Стратегии партиционирования (sharding) |
Навигация
- Предыдущий: 269
- Следующий: 271
- Индекс: 00. Индекс разборов