Сервер для RAG нельзя корректно выбрать только по объёму базы знаний, числу сотрудников или размеру LLM.
Сначала нужно описать две разные нагрузки. Первая — ingestion и indexing: сколько документов меняется, сколько chunks и embeddings требуется создать и через какое время новая версия должна стать доступна в поиске. Вторая — online serving: сколько запросов приходит одновременно, как работает filtered retrieval, сколько кандидатов обрабатывает reranker и какой token profile получает LLM.
Только после этого требования переводятся в CPU, RAM, storage, GPU и количество узлов.
CORPUS + CHANGE RATE
↓
extraction
↓
chunking
↓
embedding
↓
index update
↓
freshness SLA
+
QUERY LOAD
↓
query embedding
↓
filtered retrieval
↓
reranking
↓
context
↓
LLM
↓
latency SLA
↓
combined-load test
↓
shared
/
isolated
/
independently scaled
Главный принцип:
Актуальная NVIDIA Enterprise RAG architecture также рассматривает retrieval pipeline как несколько компонентов — RAG server, embedding, vector database, reranker и LLM — которые могут становиться отдельными bottlenecks и масштабироваться независимо. Конкретные размеры NVIDIA reference architecture при этом относятся к её моделям и software stack и не являются универсальной нормой.
Разделите RAG на ingestion и online serving

Ingestion / indexing plane
source
↓
extraction
↓
chunking
↓
embedding
↓
DB write
↓
index update
↓
searchable
Полезные единицы нагрузки:
documents/s
pages/s
chunks/s
embeddings/s
vectors/s
Например, NVIDIA в своей ingestion methodology использует documents per second или pages per second в зависимости от типа данных и способа обработки. Это хороший пример того, почему единицу нагрузки нужно выбирать по реальному pipeline, а не по объёму диска.
Online serving plane
query
↓
query embedding
↓
filtered retrieval
↓
reranking
↓
context construction
↓
LLM prefill
↓
generation
Здесь нужны другие inputs:
QPS
concurrency
retrieval Top-K
rerank candidates/request
input tokens
output tokens
TTFT
ITL
E2E latency
Одна строка:
RAG load = high
не является входными данными для инженерного расчёта.
Почему 500 GB документов не определяют сервер
Исходный corpus проходит несколько преобразований:
raw documents
≠
parsed content
≠
chunks
≠
vectors
≠
vector database footprint
На итог влияют:
document formats
parser
tokenizer
chunking strategy
chunk size
overlap
embedding dimension
datatype
dense/sparse representation
metadata
filter indexes
ANN index
replication
Минимальный corpus record:
Input | Значение |
Documents / objects | |
Pages | |
Raw bytes | |
Рост в месяц | |
PDF / DOCX / HTML | |
Scans / images | |
Tables | |
Parser + version | |
Chunker + version | |
Embedding model + version |
Число chunks лучше измерить на representative sample
Надёжный путь:
representative corpus
↓
production parser
↓
production chunker
↓
measured chunk count
↓
project estimate
Не следует использовать универсальное:
1 PDF = 40 chunks
или:
1 GB = N vectors
Если конкретный pipeline действительно использует обычное overlapping-window splitting, для предварительной оценки можно использовать:
Nchunks=1+⌈max(0,T−C)C−O⌉N_{chunks} = 1+ \left\lceil \frac{\max(0,T-C)} {C-O} \right\rceil
при C > O, где T — длина документа в токенах, C — размер chunk, O — overlap.
Raw vector payload можно рассчитать
Для N dense vectors размерности D при B bytes на один элемент:
RawVectorBytes=N×D×BRawVectorBytes=N\times D\times B
Если физическая replication равна R:
RawVectorBytesreplicated=N×R×D×BRawVectorBytes_{replicated} = N\times R\times D\times B
Это именно базовый payload vectors.
Qdrant в текущей capacity-planning documentation использует такую же основу: число points, replication, dimensions и datatype; при нескольких named vectors каждое представление считается отдельно.
Обязательные inputs:
Vector count:
Dimensions:
Datatype:
Replication:
Datatype нельзя предполагать
Нельзя автоматически считать каждый embedding как FP32.
Возможны, например:
float32
float16
uint8
и другие поддерживаемые выбранным stack representation.
Следовательно:
Dimensions:
Datatype:
должны фиксироваться вместе.
Quantization тоже не означает, что весь disk footprint сокращается в ту же пропорцию. В Qdrant, например, quantized representation хранится наряду с original vectors; конфигурация может уменьшать RAM working set, не удаляя исходные vectors с диска. Сам Qdrant рекомендует отдельно проверять качество поиска после quantization.
Raw vectors — не размер vector DB
Полный storage/RAM footprint может дополнительно включать:
ANN index
sparse-vector index
if used
payload / metadata
payload indexes
IDs
quantized copies
WAL
temporary optimization data
snapshots
replicas
Qdrant, например, рассчитывает dense vectors, HNSW, payload, payload indexes и ID tracker как самостоятельные structures. Их placement между RAM и disk также настраивается отдельно.
Поэтому нельзя использовать vendor-neutral shortcut:
Vector DB size =
raw vectors × 1.2
Корректнее:
Слой | Как получать |
Dense raw vectors | CALCULATED |
Sparse vectors, если есть | CALCULATED / STACK-SPECIFIC |
ANN/vector index | STACK-SPECIFIC |
Metadata/payload | MEASURED / ESTIMATED |
Filter indexes | STACK-SPECIFIC |
WAL / temporary data | STACK-SPECIFIC |
Replication | EXPLICIT |
Backup / snapshots | EXPLICIT |
Actual DB footprint | MEASURED |
Если database/index ещё не выбран:
FULL DB FOOTPRINT:
CONDITIONAL
Hybrid search нужно считать отдельно
Некоторые RAG systems используют одновременно dense и sparse retrieval.
В таком случае нельзя применить формулу dense-vector payload ко всему индексу.
Нужно отдельно учитывать:
dense vectors
dense ANN index
sparse representation
sparse index
metadata/filter indexes
Например, Qdrant capacity guidance отдельно считает sparse vectors по числу ненулевых элементов, а не по dense dimension.
Для ingestion важнее change rate, чем только total corpus
После initial load система обычно продолжает получать:
new documents
changed documents
deleted documents
Поэтому нужны:
New documents/day:
Changed documents/day:
Deleted documents/day:
Peak update batch:
Allowed processing window:
Для простого workload budget:
RequiredDocsPerSecond=DocumentsToProcessAvailableProcessingWindowSecondsRequiredDocsPerSecond= \frac{DocumentsToProcess} {AvailableProcessingWindowSeconds}
Для page-oriented extraction:
RequiredPagesPerSecond=PagesToProcessAvailableProcessingWindowSecondsRequiredPagesPerSecond= \frac{PagesToProcess} {AvailableProcessingWindowSeconds}
А для embedding stage:
RequiredEmbeddingsPerSecond=EmbeddingsToCreateAvailableProcessingWindowSecondsRequiredEmbeddingsPerSecond= \frac{EmbeddingsToCreate} {AvailableProcessingWindowSeconds}
Это требование к workload, а не заявленная производительность CPU или GPU.
Freshness нужно считать до searchable state
Для корпоративной базы знаний полезен отдельный KPI:
UpdateLag=tsearchable−tsource changeUpdateLag= t_{searchable}-t_{source\ change}
Например, бизнес может требовать, чтобы изменённый документ появлялся в production retrieval не позже определённого времени после изменения источника.
В UpdateLag могут входить:
source sync
extraction
chunking
embedding
DB write
index update
visibility
Поэтому завершение embedding job ещё не обязательно означает, что новые сведения доступны пользователю.
Для exact vector DB нужно определить её реальные semantics:
durably written
searchable
fully indexed / optimized
и не переносить поведение одного продукта на другой.
Initial load и steady-state ingestion — разные тесты
Нужно минимум два ingestion profile.
Сценарий | Что проверяем |
Initial / bulk load | сколько времени занимает загрузка существующей базы |
Steady-state | укладываются ли регулярные изменения в freshness SLA |
Третий профиль — самый важный для architecture decision:
Steady-state ingestion одновременно с production query workload.
При массовой загрузке Qdrant, например, одновременно работает с writes, indexing и optimizer operations; его документация отдельно предупреждает о нагрузке на память, диск и search performance во время bulk ingestion.
Это stack-specific пример общего принципа: ingestion нельзя считать полностью независимым от retrieval, если они делят ресурсы.
Число сотрудников не равно concurrency
Фраза:
система для 5 000 сотрудников
не означает:
5 000 concurrent requests
Для online workload нужны:
Baseline QPS:
Peak QPS:
Peak concurrency:
Burst duration:
Arrival profile:
Evidence:
MEASURED / FORECAST / ASSUMPTION
NVIDIA sizing guide тоже использует concurrent requests и latency constraint как непосредственные параметры sizing. В самой документации есть пример оценки concurrency из доли пользователей, но такой процент относится к её sizing example и не должен становиться универсальной формулой Start Server.
Если известен только штат сотрудников, concurrency нужно сначала смоделировать или измерить отдельно.
QPS и concurrency не взаимозаменяемы
QPS отвечает на вопрос:
Сколько запросов приходит или завершается за секунду?
Concurrency:
Сколько запросов одновременно находятся в работе?
При длинных запросах умеренный QPS может создавать высокую concurrency.
Поэтому оба параметра сохраняются отдельно.
Production retrieval benchmark должен включать filters
В корпоративной системе запрос нередко ограничивается:
tenant
department
group
document type
security classification
project
Benchmark без таких условий может не отражать production retrieval.
Qdrant, например, рекомендует payload indexes для полей, используемых при filtering; эти индексы влияют на структуру vector index и сами требуют ресурсов.
Поэтому record должен содержать:
Production filters:
Filter fields:
Indexing:
Filter selectivity:
ACL correctness и filter performance — разные задачи
SS-021 занимается infrastructure sizing.
Поэтому разделяем:
SECURITY CORRECTNESS
может ли этот пользователь
видеть документ?
и:
FILTER PERFORMANCE
укладывается ли retrieval
с production ACL filters
в SLA?
Второе входит в benchmark.
Первое требует отдельного security review.
Retrieval latency без Top-K почти бесполезна
Результат:
Vector search = 20 ms
нужно сопровождать:
Vector count:
Dimensions/datatype:
Index/version:
Filters:
Top-K:
QPS:
Concurrency:
Hardware:
Software version:
NVIDIA также использует Top-K как отдельный параметр RAG workload, наряду с concurrency, chunk size и input/output sequence length.
Но конкретные рекомендуемые значения Top-K из одной reference architecture не становятся default для другого RAG.
Retrieval Top-K и context Top-N — разные параметры
Если используется reranker:
retrieval
→ K candidates
→ reranker
→ N chunks
→ LLM
где обычно:
N≤KN\leq K
если именно так устроен pipeline.
Поэтому храните две строки:
Retrieval Top-K:
Reranker output Top-N:
Это важно и для retrieval load, и для downstream token profile.
Reranker не обязателен для каждого RAG
В worksheet:
Reranker:
USED / NOT USED / TEST
Model/version:
Если reranker есть, удобная workload metric:
CandidatePairsPerSecond=QPS×CandidatesPerQueryCandidatePairsPerSecond = QPS\times CandidatesPerQuery
Например:
40 QPS
× 25 candidates
=
1 000 query-document pairs/s
Это только арифметическое описание нагрузки.
Из него нельзя заключить:
нужна GPU X
без benchmark конкретного reranker, runtime, precision и batching.
Generation начинается с token profile
Для LLM нужны:
Model/version:
Precision:
Base prompt tokens:
Retrieved-context tokens:
Total input tokens:
Output tokens:
Peak concurrency:
Название модели само по себе недостаточно.
Актуальный vLLM отдельно собирает distributions prompt tokens и generation tokens, что позволяет анализировать фактический serving profile, а не только model name.
TTFT, ITL и E2E нельзя смешивать
Для streaming LLM полезно разделять:
Метрика | Что помогает понять |
Queue time | сколько запрос ожидает scheduling |
TTFT | задержку до первого output token |
ITL / TPOT | скорость продолжения генерации |
E2E | общую пользовательскую задержку |
Точная семантика начала/конца каждой метрики зависит от serving runtime и версии, поэтому в benchmark нужно хранить tool/version.
vLLM, например, отдельно экспортирует TTFT, inter-token latency, end-to-end latency, running/waiting requests, а также prefill/decode-related metrics.
Это помогает не путать:
slow generation
с:
request waits
because service is saturated
Queue time — отдельный bottleneck signal
Если TTFT вырос, это ещё не означает, что нужна более быстрая GPU.
Причиной могут быть:
queueing
high concurrency
long prefill
KV-cache pressure
scheduler capacity
vLLM отдельно показывает waiting requests и queue intervals именно для такого анализа.
Поэтому generation record включает:
Waiting requests:
Queue latency:
TTFT:
ITL:
E2E:
RAG Latency Budget
Для design stage используйте бюджет:
Stage | Target | p50 | p95 | p99 | Conditions |
Query embedding | |||||
Filtered retrieval | |||||
Reranking | |||||
Context/orchestration | |||||
LLM TTFT | |||||
Generation / ITL | |||||
End-to-end |
Stage budget не равен фактическому critical path

Для предварительной модели можно написать:
Tbudget=Tembed+Tretrieve+Trerank+Tcontext+TLLMT_{budget} = T_{embed} + T_{retrieve} + T_{rerank} + T_{context} + T_{LLM}
Но runtime может содержать:
parallel operations
async execution
overlap
cache hits
queueing
streaming
Поэтому эта сумма — budgeting tool, а не доказательство фактической E2E latency.
Факт берётся из end-to-end measurement и trace.
Среднего значения недостаточно
average latency = 600 ms
может скрывать длинный tail.
Поэтому benchmark должен заранее определить:
Target percentile:
p95 / p99 / project-defined
Target:
Measured:
Нет универсального:
p95 < 2 seconds
для любого корпоративного RAG.
Target зависит от use case.
Быстрый retrieval бесполезен, если качество стало неприемлемым
Изменение:
Top-K
index parameters
quantization
search mode
может менять и performance, и retrieval quality.
Поэтому рядом с latency:
Retrieval evaluation dataset:
Quality metric:
Target:
Measured:
Qdrant, например, прямо рекомендует проверять recall при использовании quantization.
Universal recall threshold статья не назначает.
Нужно ли vector DB полностью помещать в RAM
Универсального ответа нет.
Конкретные vector stores позволяют по-разному размещать vectors, indexes и payload structures.
Например, Qdrant различает memory tiers для dense vectors, HNSW, payload, payload indexes и quantized representations. Это создаёт разные RAM/disk/latency trade-offs.
Поэтому нельзя писать ни:
Vector DB всегда должна полностью помещаться в RAM.
ни:
Vector DB всегда можно держать на NVMe без влияния на latency.
Проверяется exact stack и working set.
Главный тест: query и ingestion одновременно
Перед решением один сервер или несколько нужны три режима.
TEST A
production query load
without ingestion
TEST B
target ingestion/update load
without online queries
TEST C
production query load
+
target ingestion load
Во всех трёх режимах измеряем:
CPU
RAM
storage latency / throughput
GPU / VRAM where relevant
retrieval p95/p99
reranker latency
LLM queue
TTFT / ITL / E2E
UpdateLag
Как трактовать combined-load test
Если:
A = PASS
B = PASS
C = PASS
shared deployment остаётся жизнеспособным кандидатом.
Если:
A = PASS
B = PASS
C = FAIL
доказан конфликт ресурсов при совместной нагрузке.
Но ещё не доказано, что требуется новый физический сервер.
Следующие варианты могут включать:
tuning
resource limits
different scheduling
memory/storage placement
service isolation
independent scale-out
Когда компонент становится отдельным scaling domain
Наблюдение | Следующий архитектурный вопрос |
LLM queue растёт, retrieval стабилен | масштабировать generation? |
Retrieval SLA нарушается при свободном LLM | нужен независимый search tier? |
Reranker saturates отдельно | масштабировать reranking? |
Ingestion ухудшает online latency | schedule/isolate/separate ingestion? |
Index footprint упирается в RAM/storage | менять VDB topology/placement? |
Service требует независимого HA/restart cycle | отделить failure domain? |
NVIDIA reference design также масштабирует LLM, embedding, reranker, RAG server и vector DB nodes по bottleneck соответствующего компонента. Это подтверждает принцип независимых scaling domains, но не её конкретные resource ratios как универсальный sizing rule.
Production не означает автоматически multi-node
Нельзя использовать:
production RAG
=
минимум 3 сервера
Перед HA design нужны:
Availability target:
RTO:
RPO:
Maintenance window:
Allowed degraded mode:
Single-node может пройти performance requirements, но не пройти availability requirements.
Это разные решения.
RAG Architecture & Sizing Worksheet

Ниже — основной самостоятельный инструмент статьи.
USE CASE
Use case:
Departments:
Availability target:
RTO:
RPO:
End-to-end latency target:
Target percentile:
CORPUS
Documents:
Pages / objects:
Raw bytes:
Growth/month:
Formats:
PDF:
DOCX:
HTML:
Scans:
Tables:
Images:
Representative sample:
PARSING / CHUNKING
Parser/version:
Tokenizer/version:
Chunking method:
Chunk size:
Overlap:
Measured chunks/sample:
Estimated total chunks:
Status:
MEASURED /
ASSUMPTION /
UNKNOWN
EMBEDDINGS
Model/version:
Dense:
YES / NO
Dimensions:
Datatype:
Sparse/hybrid:
YES / NO
Replication:
UPDATES
New documents/day:
Changed documents/day:
Deleted documents/day:
Peak batch:
Available update window:
Required docs/s:
Required pages/s:
Required embeddings/s:
Maximum UpdateLag:
VECTOR STORAGE
Vector DB/version:
Index/version:
Dense vector count:
Dense raw bytes:
Sparse structures:
if applicable
ANN/vector index:
Metadata/payload:
Filter indexes:
WAL/temp:
Replication:
Snapshots/backup:
Measured DB footprint:
RETRIEVAL
Baseline QPS:
Peak QPS:
Peak concurrency:
Burst duration:
Production filters:
ACL-related filters:
Retrieval Top-K:
Quality metric:
Target:
p50:
p95:
p99:
RERANK
USED /
NOT USED /
TEST
Model/version:
Candidates/request:
Output chunks/request:
Peak requests/s:
Candidate pairs/s:
Concurrency:
p50:
p95:
p99:
GENERATION
LLM/version:
Precision:
Base prompt tokens:
Retrieved-context tokens:
Total input tokens:
Output tokens:
Peak concurrency:
Waiting requests:
Queue latency:
TTFT:
ITL / TPOT:
E2E:
COMBINED LOAD
A — query only:
PASS / FAIL
B — ingestion only:
PASS / FAIL
C — query + ingestion:
PASS / FAIL
RESOURCE OBSERVATION
CPU:
RAM:
Storage latency:
Storage throughput:
GPU:
VRAM:
Network:
Other:
DEPLOYMENT
Extraction:
SHARED / ISOLATED /
SEPARATE / TEST
Embedding:
SHARED / ISOLATED /
SEPARATE / TEST
Vector DB:
SHARED / ISOLATED /
SEPARATE / TEST
Reranker:
SHARED / ISOLATED /
SEPARATE / TEST
LLM:
SHARED / ISOLATED /
SEPARATE / TEST
RESULT
Primary bottleneck:
Freshness SLA:
PASS / FAIL
Retrieval SLA:
PASS / FAIL
Generation SLA:
PASS / FAIL
E2E SLA:
PASS / FAIL
Independent scaling required:
YES / NO / TEST
Critical unknowns:
...
Как трактовать результат
Не выводите конкретный сервер, если критические workload inputs неизвестны.
Используем четыре состояния:
Статус | Значение |
SIZED | workload/SLA подтверждены и architecture прошла требуемый benchmark |
CANDIDATE | предварительный sizing есть, требуется validation |
CONDITIONAL | результат зависит от software/index/config assumption |
INSUFFICIENT DATA | критических данных для sizing нет |
Например, если неизвестны:
chunk/vector count
peak concurrency
production filters
Top-K
token profile
freshness SLA
latency SLA
правильный вывод:
INSUFFICIENT DATA
а не выбор SKU по размеру исходной папки.
Scaling Domain Matrix
Component | Load driver | KPI | Возможный конфликт | Decision |
Extraction | docs/pages over time | docs/s, pages/s | CPU/GPU/RAM | |
Embedding | chunks/time | embeddings/s | compute | |
Indexing | vectors/updates | UpdateLag | CPU/RAM/I/O | |
Retrieval | QPS + filters | p95/p99 + quality | RAM/I/O/CPU/GPU by stack | |
Reranking | QPS × candidates | pairs/s + latency | compute | |
LLM | tokens + concurrency | queue/TTFT/ITL/E2E | GPU/VRAM | |
Storage | corpus/index growth | capacity/I/O | NVMe/storage |
Колонка resource не должна заранее превращаться в:
embedding = GPU
retrieval = CPU
Практический порядок расчёта
1. Зафиксировать corpus
↓
2. Прогнать representative sample
↓
3. Получить chunk/vector count
↓
4. Зафиксировать change rate
↓
5. Определить UpdateLag SLA
↓
6. Получить ingestion target
↓
7. Рассчитать raw vector payload
↓
8. Получить stack-specific DB footprint
↓
9. Зафиксировать production filters
↓
10. Определить QPS + concurrency
↓
11. Benchmark filtered retrieval
↓
12. Зафиксировать Top-K
↓
13. Получить reranker workload
↓
14. Зафиксировать LLM token profile
↓
15. Проверить queue / TTFT / ITL / E2E
↓
16. Запустить query-only test
↓
17. Запустить ingestion-only test
↓
18. Запустить combined-load test
↓
19. Определить bottleneck
↓
20. Выбрать:
shared / isolated /
independently scaled
Какие данные нужны для подбора
Для первичного sizing достаточно собрать:
CORPUS
documents / pages
formats
raw volume
growth
CHANGE PROFILE
new documents/day
changed documents/day
update window
freshness SLA
PIPELINE
parser/chunker
embedding model
vector DB/index
if already selected
filters / ACL requirements
QUERY LOAD
peak QPS
peak concurrency
burst profile
retrieval Top-K
RERANK
used / not used
model
candidates/query
LLM
model/version
precision
input tokens
retrieved context
output tokens
concurrency
SLA
UpdateLag
retrieval latency
TTFT / ITL / E2E
availability
RTO / RPO
Если данных пока нет, preliminary sizing должен явно помечать их как ASSUMPTION или UNKNOWN.
Получить консультацию
Оставьте заявку и наш менеджер свяжется с вами для консультации









