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 nền
Phần tiêu đề “Công thức nền”Công thức Qdrant đưa ra cho trường hợp giữ toàn bộ vector trong bộ nhớ:
Hệ số 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.
Bảng tra nhanh
Phần tiêu đề “Bảng tra nhanh”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ều | RAM cho 1 triệu vector | Ghi chú |
|---|---|---|
| 384 | ~2,1 GiB | Model nhỏ, MiniLM-cỡ |
| 768 | ~4,3 GiB | Đa số model câu tiếng Việt |
| 1024 | ~5,7 GiB | Con số ví dụ của Qdrant |
| 1536 | ~8,6 GiB | text-embedding-3-small |
| 3072 | ~17,2 GiB | text-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 GiBCon số đó thường là lúc người ta bắt đầu nghiêm túc về quantization.
Sau khi nén
Phần tiêu đề “Sau khi nén”Từ cùng công thức, phần vector (chưa tính hệ số 1,5):
| Cách | Byte/chiều | 1 triệu × 1536 chiều |
|---|---|---|
| float32 | 4 | 6,1 GB |
| float16 | 2 | 3,1 GB |
| scalar int8 (4×) | 1 | 1,5 GB |
| TurboQuant 4-bit (8×) | 0,5 | 0,77 GB |
| binary / TQ 1-bit (32×) | 0,125 | 0,19 GB |
| PQ ×64 | ~0,06 | 0,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 đó.
Quy tắc ngón tay cái quan trọng nhất
Phần tiêu đề “Quy tắc ngón tay cái quan trọng nhất”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.
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.
Những thứ hay bị quên trong dự toán
Phần tiêu đề “Những thứ hay bị quên trong dự toán”| Khoản | Vì sao dễ quên |
|---|---|
| Đĩa cho lúc optimizer chạy | Merge/dựng lại giữ đồng thời bản cũ và bản mới |
| Đĩa cho snapshot | Snapshot là bản sao gần như đầy đủ (7.19) |
replication_factor | Nhân đôi mọi thứ. Nhưng nếu bạn chưa bật, xem lại 7.15 |
| Payload index | memory: pinned mặc định — luôn nằm RAM (7.9) |
| Đĩa cho inline storage | Tăng 3–4× nếu bạn bật nó (7.10) |
| Chuyển shard | Phươ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ế.
Hạn ngạch tài nguyên — hàng rào cuối
Phần tiêu đề “Hạn ngạch tài nguyên — hàng rào cuối”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_percent | Từ 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_percent | Từ chối cập nhật khi phân vùng chứa storage đầy tới % này |
release_margin_percent | Phả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.
Quy trình sizing, sáu bước
Phần tiêu đề “Quy trình sizing, sáu bước”- 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.
- Ước phần nóng. Bao nhiêu phần trăm corpus thật sự được truy cập hằng tuần?
- Cộng đệm 30–50% cho optimizer, snapshot, payload index.
- Nhân với
replication_factor. - Nạp thử 10% dữ liệu thật, đo RAM/đĩa thực tế, ngoại suy tuyến tính.
- Đ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.