IVFPQ — skip most cells, compress the rest

IVFPQ stacks the two earlier ideas — IVF cells skip most of the data and PQ compresses what survives (quantizing each vector's residual from its centroid) — giving the FAISS billion-scale workhorse: small memory AND a fraction-of-N scan, paid for with compounded approximation that re-ranking partly buys back.

Previously

PQ shrank the vectors but still touched all of them; IVF skipped most vectors but stored them whole. IVFPQ does both — open only nearby cells, then store each survivor as a tiny compressed residual — and becomes the only index that fits a billion vectors in RAM at speed. We now have four very different dots on the chart, and it's time to see what they collectively prove.

Scene 09

IVFPQ — skip most cells, compress the rest

  1. Watch
  2. Try it
  3. Predict
  4. Capture
VECTOR · 1,536 dims · 32 subvectorsd0d1d2d3d4d5d6d7d8d9d10d11d12d13d14d15d16d17d18d19d20d21d22d23… 32each chunk = 48 dims = 192 raw bytesCODEBOOK · 256 prototypesnearest prototype → 1 byte (id 0–255)PQ CODE · 32 bytes1779819196117382151365723415576000000000000… 32BYTES PER VECTORraw float326,144→PQ code32192×smallerRECALL0.59lossyPQ approx onlyIVF CELLS · probe nearestPQ encodes the RESIDUAL (point − centroid)RECALL vs LATENCYrecall ↑latency →FlatHNSWIVFPQIVF opens only the nearby cells; PQ stores each survivor's residual as a few bytes.
residual = point − its cell's centroid
only nearby cells opened
6,144 bytes → a handful
What to watch for

We're not inventing anything new here — we're stacking two tools you already have. IVF carves the 14 songs into a few cells and, for the query 'Now Playing', opens only the nearby ones (everything else stays dimmed and unscanned). Then, for the songs that survive in those opened cells, PQ shrinks each one. The twist: PQ doesn't compress the raw vector — it compresses the RESIDUAL, which just means 'how far this point sits from the centre of its cell.' Because every point in a cell is already huddled near that centre, the residual is a small wobble, and small wobbles round to a prototype far more accurately than a whole vector would. Watch the byte counter collapse from 6,144 bytes (1536 dimensions × 4 bytes each) down to a handful, while only the nearby cells light up.

Implementation

Highlighted lines are the ones running in the diagram right now.

IVFPQ.add
store each vector as (cell id, PQ code of its residual)
def add(vec):
c = nearest_centroid(vec) # IVF: which cell
residual = vec - centroids[c] # the small leftover
code = pq.encode(residual, m) # m one-byte ids
cells[c].append((id_of(vec), code))
IVFPQ.search
open nprobe cells, then score the survivors
def search(q, k, nprobe, rerank):
near = nprobe_nearest_cells(q, nprobe)
cands = []
for c in near: # the rest stay closed
cands += pq_score(q, c)
short = top(cands, 4 * k) # cheap shortlist
if rerank:
short = exact_rescore(q, short)
return top(short, k)
PQ.score (ADC)
score codes against the query residual, no decompression
def pq_score(q, c):
qr = q - centroids[c] # query residual for this cell
# one table per subvector: qr-chunk -> each prototype
table = adc_tables(qr, m)
out = []
for (id, code) in cells[c]:
d = sum(table[j][code[j]] for j in range(m))
out.append((id, d))
return out

Where this sits in Build a vector database (Pinecone / Weaviate / pgvector style)

Scene 09 of 15, in the Compress & pick act — PQ shrinks 6 KB to 96 bytes, IVFPQ combines both, and the trilemma forces a choice.. Stack IVF (skip most cells) and PQ (compress the residual): the FAISS billion-scale workhorse — tiny memory and a fraction-of-N scan, paid for with compounded approximation.

Up next. Look at the four dots we've placed: Flat owns recall, HNSW owns speed-at-recall but eats RAM, IVFPQ owns memory but eats recall. No single dot is best at everything. That's not an accident of our toy dataset — it's the organizing law of the whole field. Let's make it explicit.

All 15 scenes in Build a vector database (Pinecone / Weaviate / pgvector style) · Every curriculum

Built with Arqly
Every scene in Build a vector database (Pinecone / Weaviate / pgvector style) builds on the one before it.All 15 Build a vector database (Pinecone / Weaviate / pgvector style) scenes