Bỏ qua để đến nội dung
Search & RAG

7.18 Toán tài nguyên và sizing

Mục này để bạn trả lời được câu hỏi “cần máy bao nhiêu RAM?” trước khi trả tiền, chứ không phải sau khi bị OOM.

Công thức Qdrant đưa ra cho trường hợp giữ toàn bộ vector trong bộ nhớ:

RAMsoˆˊ vector×soˆˊ chieˆˋu×4 byte×1,5\text{RAM} \approx \text{số vector} \times \text{số chiều} \times 4\ \text{byte} \times 1{,}5

Hệ số 1,51{,}5 dành cho metadata, index, phiên bản điểm, và segment tạm sinh ra trong lúc optimizer chạy.

Hệ số 1,5 là phần người ta hay quên, và nó không nhỏ. Nó tồn tại vì hai lý do rất thực: đồ thị HNSW tốn khoảng m × 8 byte mỗi vector, và trong lúc merge/dựng lại, optimizer giữ đồng thời cả bản cũ lẫn bản mới.

Ví dụ Qdrant đưa: 1 triệu vector × 1024 chiều ≈ 5,72 GB.

Kiểm lại: 1.000.000 × 1024 × 4 × 1,5 = 6.144.000.000 byte = 5,72 GiB. Khớp.

Toán tay theo công thức trên cho 1 triệu vector (toán tay, giả định float32 và hệ số 1,5):

Số chiềuRAM cho 1 triệu vectorGhi chú
384~2,1 GiBModel nhỏ, MiniLM-cỡ
768~4,3 GiBĐa số model câu tiếng Việt
1024~5,7 GiBCon số ví dụ của Qdrant
1536~8,6 GiBtext-embedding-3-small
3072~17,2 GiBtext-embedding-3-large

Nhân lên theo quy mô, và nhân tiếp với replication_factor:

10 triệu chunk × 1536 chiều × replication_factor 2 ≈ 172 GiB

Con số đó thường là lúc người ta bắt đầu nghiêm túc về quantization.

Từ cùng công thức, phần vector (chưa tính hệ số 1,5):

CáchByte/chiều1 triệu × 1536 chiều
float3246,1 GB
float1623,1 GB
scalar int8 (4×)11,5 GB
TurboQuant 4-bit (8×)0,50,77 GB
binary / TQ 1-bit (32×)0,1250,19 GB
PQ ×64~0,060,10 GB

⚠️ Nhắc lại 7.10: các dòng nén là kích thước của bản nén. Nếu bạn vẫn giữ vector gốc trong RAM thì cộng thêm, không phải thay thế. Chỉ khi vector gốc chuyển sang cold thì bạn mới thật sự thu được khoản tiết kiệm đó.

Qdrant phát biểu nó rất gọn, và nó là thứ nên nhớ hơn cả công thức:

Nếu bạn chỉ giữ được một nửa số vector trong RAM, latency tìm kiếm xấp xỉ gấp đôi.

Từ đó suy ra một cách tính chi phí thực dụng hơn nhiều so với “tính cho toàn bộ corpus”: hãy tính cho phần dữ liệu nóng.

RAMsoˆˊ vector ĐANG ĐƯỢC TRUY CẬP×soˆˊ chieˆˋu×4×1,5\text{RAM} \approx \text{số vector ĐANG ĐƯỢC TRUY CẬP} \times \text{số chiều} \times 4 \times 1{,}5

Nếu 90% truy vấn chỉ chạm 10% corpus — chuyện rất thường gặp: tài liệu mới, sản phẩm phổ biến, tenant hoạt động — thì bạn không cần RAM cho 100%. Để phần còn lại ở cold, và page cache của hệ điều hành sẽ tự giữ đúng phần nóng (7.5).

Đây là chỗ tiết kiệm tiền lớn nhất, và nó không đòi hỏi bạn hy sinh recall như quantization.

KhoảnVì sao dễ quên
Đĩa cho lúc optimizer chạyMerge/dựng lại giữ đồng thời bản cũ và bản mới
Đĩa cho snapshotSnapshot là bản sao gần như đầy đủ (7.19)
replication_factorNhân đôi mọi thứ. Nhưng nếu bạn chưa bật, xem lại 7.15
Payload indexmemory: pinned mặc định — luôn nằm RAM (7.9)
Đĩa cho inline storageTăng 3–4× nếu bạn bật nó (7.10)
Chuyển shardPhương pháp snapshot cần thêm dung lượng tạm

Cộng lại, khoảng đệm 30–50% trên con số tính toán thuần là hợp lý — và nếu bạn dùng phương pháp chuyển shard snapshot, cần hơn thế.

Từ v1.19, Qdrant có quota API ở mức cụm, thay cho tham số max_resident_memory_percent cũ:

Tham sốNghĩa
max_resident_memory_percentTừ chối các cập nhật tốn bộ nhớ khi RSS vượt % này của tổng RAM (hoặc của giới hạn cgroup)
max_disk_usage_percentTừ chối cập nhật khi phân vùng chứa storage đầy tới % này
release_margin_percentPhải tụt xuống dưới ngưỡng bao nhiêu điểm phần trăm thì mới nhận việc trở lại (mặc định 5)

release_margin_percent là chi tiết thiết kế đáng học ngoài phạm vi Qdrant: nếu không có biên nhả, một tài nguyên nằm sát ngưỡng sẽ khiến node liên tục vào–ra khỏi trạng thái phục vụ theo nhiễu giữa hai lần đo. Đây là hysteresis, và mọi hệ thống có ngưỡng đều cần nó.

Ngoài ra có strict mode ở mức collection, đặt trần cho những gì client được phép yêu cầu: max_query_limit, max_timeout, search_max_hnsw_ef, search_max_oversampling, search_allow_exact, và — rất hữu ích — unindexed_filtering_retrieve để cấm lọc trên trường chưa đánh index.

Cái cuối cùng đó đáng bật ngay trong môi trường có nhiều người dùng API: nó biến lỗi thầm lặng ở 7.9 thành một lỗi rõ ràng, ngay lúc phát triển.

  1. Tính theo công thức cho dữ liệu bạn dự kiến có sau 12 tháng, không phải hôm nay.
  2. Ước phần nóng. Bao nhiêu phần trăm corpus thật sự được truy cập hằng tuần?
  3. Cộng đệm 30–50% cho optimizer, snapshot, payload index.
  4. Nhân với replication_factor.
  5. Nạp thử 10% dữ liệu thật, đo RAM/đĩa thực tế, ngoại suy tuyến tính.
  6. Đo latency có filter, có tải ghi — đó mới là điều kiện production (7.6, 7.8).

Bước 5 là bước hay bị bỏ và cũng là bước cứu bạn nhiều nhất. Ngoại suy từ 10% dữ liệu thật đáng tin hơn nhiều so với bất kỳ công thức nào — kể cả công thức ở đầu mục này.

Phần 7 — Qdrant