跪拜 Guibai
← All articles
GitHub

Squeeze 10M Vector Search into 2GB RAM: A faiss 1.7.4 Playbook

By 穆梓兰煊 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Ten-million-scale vector search doesn't require a commercial database or a large-RAM box; a single 16GB node suffices if you pick the right faiss version and compress properly. The trade-off is precision: 92.3% recall@10 is fine for many production use cases, but the article's numbers give a concrete target to tune from if your recall bar is higher.

Summary

Running vector search at the 10-million scale on a 16GB node requires more than just loading float vectors. Uncompressed, 10M 768-dim float32 vectors take roughly 3GB, and the accompanying HNSW index adds 3–5× that, blowing past 12GB. The article's fix is a specific stack: faiss 1.7.4, product quantization (PQ) with m=12 and nbits=8, and an IVF index with nlist set to the square root of the vector count.

Measured results on a 16GB server: vector memory drops from 3GB to 10MB (1 byte per vector), total index memory falls from 12GB to 2GB, and recall@10 settles at 92.3% versus 99.5% uncompressed. The article also walks through the failure modes: training samples below 100× the subspace count drive recall under 65%, and forgetting to disable GPU causes OOM. It recommends pinning faiss to 1.7.4, since 1.7.5 adds no compression features and has binding issues.

Takeaways
— faiss 1.7.4 is the only Python-bound open-source library with deep vector compression support; 1.7.5 adds no new compression features and has Python binding compatibility issues.
— Uncompressed 10M 768-dim float32 vectors take ~3GB; HNSW or similar index structures add 3–5× more memory.
— PQ with m=12 and nbits=8 compresses each 768-dim float32 vector (3KB) down to 1 byte, reducing 10M vectors to 10MB.
— Total index memory for the PQ+IVF setup is 2GB on a 16GB server, versus 12GB uncompressed.
— Recall@10 drops from 99.5% (uncompressed) to 92.3% with these settings.
— IVF's nlist should be set to the square root of the vector count: ~3162 for 10M, rounded to 3000 in the example; this improves search speed by 10–100×.
— Training samples must be at least 100× the number of subspaces; 1000 samples (10× for m=12) dropped recall below 65%.
— Use faiss-cpu explicitly to avoid GPU memory allocation and OOM.
— Recommended m range is 1/64 to 1/32 of vector dimension (e.g., 12 for d=768) to balance precision and compression.
— A compression ratio of 3000 (3GB to 1MB) still yields 92.3% recall@10 in this scenario.
Conclusions

Pinning to faiss 1.7.4 over 1.7.5 — despite the newer version adding nothing relevant — suggests that Python binding stability drives production adoption more than feature velocity.

Losing only 7.2 percentage points of recall@10 at a 3000:1 compression ratio shows PQ's efficiency for approximate retrieval, but the article never addresses high-recall requirements, so this path isn't a blanket answer.

The nlist square-root rule is a heuristic that trades precision for speed; it's simple to apply, but real workloads with skewed vector distributions may need a different split.

Concepts & terms
Product Quantization (PQ)
A lossy compression method that splits a high-dimensional vector into subspaces and quantizes each subspace into a code; at query time, distances are approximated from these codes. Here it compresses each 768-dim float32 vector to 1 byte.
IVF (Inverted File Index)
An index structure that clusters vectors into nlist centers, then only searches the cluster(s) closest to the query. The nlist parameter controls the number of clusters and directly affects speed and precision.
Recall@10
The fraction of queries where the correct result appears among the top 10 returned items. Used here to measure retrieval quality: 99.5% uncompressed versus 92.3% with PQ compression.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗