What to do when the index no longer fits in memory, the compression trick that puts the error where the score cannot see it, and how to choose among all five.
You need one read for its neighbour list — and 32 more for the neighbours’ vectors, just to decide which way to step.
~2,000 disk reads at roughly 100 µs each.
32 of the 33 reads are for scoring. Even solved perfectly, 60 structure reads is still 6 ms.
Compressed copies in RAM kill the scoring reads. A flat graph reduces the hops.
Document 09 established that a graph walk defeats the prefetcher, and that no memory ordering fixes it — a node belongs to many neighbourhoods at once, so it cannot be contiguous with all of them. Most treatments present that as bad news. DiskANN treats it as an opportunity.
A hop has two distinct needs, and separating them is the key to the whole design. To pick a direction you need the neighbours’ vectors. To continue you need the chosen node’s neighbour list. Those can be served from two different places.
Compressed copies of every vector in RAM — ~10 GB at a hundred million. Full vectors and the graph on SSD.
The 32 neighbours’ vectors, answered with zero disk reads.
One read of one 4 KB page for the chosen node’s neighbour list.
Fetch ~100 full-precision vectors and re-score them exactly.
The compressed vectors are lossy, which would be alarming if they decided the answer. They do not — they decide the direction. During the walk the question is “which of these thirty-two is closer?”, and an approximate answer is fine: pick the second-best neighbour and you have still moved toward the answer, and the next hop corrects.
After idea one, a query is sixty hops × one disk read × 100 µs = six milliseconds of pure waiting. Still too slow. HNSW gets its long jumps from sparse upper layers. Vamana gets them from a pruning rule that puts long and short edges in the same neighbour list.
A large pool of candidates for C’s neighbour list, by searching the graph.
Then repeat until the list is full or the candidates run out.
Discard any candidate lying in roughly the same direction as something already kept.
Spread across directions — some near, some far. Ten hops instead of sixty.
The maximum neighbour-list length — DiskANN’s M.
The search candidate list — DiskANN’s efSearch.
How aggressively the pruning rule discards same-direction candidates.
Worth stating cleanly, because interviewers use the names loosely. Vamana is the graph construction — edge selection and the pruning rule. DiskANN is the whole system: a Vamana graph, plus compressed vectors in RAM, plus full vectors and the graph on SSD, plus a full-precision re-rank.
DiskANN asked where should the vectors live? ScaNN asks: given that we are going to compress, can we compress more cleverly?
You replace the real vector with a catalogue entry, and it is not the same vector.
Being wrong about the number of apples changes the bill. Being wrong about the bag colour does not.
The part of the gap pointing along the query changes the score. The part pointing sideways barely does.
Accurate along the vector’s own direction, sloppy sideways.
Minimises plain squared distance.
A weighted loss that penalises error along the vector’s own direction more heavily.
“You do not know the query at build time.” And the answer: a document’s own direction is the best available proxy, because the queries that will retrieve it point roughly toward it.
The absence of an index.
Prune by region.
Prune by path.
HNSW’s answer to running out of RAM.
A better quantisation objective, packaged with an index.
How many vectors, and how big? This gives the RAM number, and the RAM number usually eliminates two options immediately.
What is the latency budget? Not “as fast as possible” — a number. If you are spending 5 ms of a 50 ms budget, speed is worth nothing to you.
What is the write pattern? Continuous edits favour a graph; bulk rebuilds favour a partition.
Is there a filter on every query? If yes, partition-based indexes are structurally disadvantaged.
Internal wiki, 20 users.
p95 under 50 ms, filters on four fields, continuous edits.
Rebuilt nightly from a warehouse, 200 ms budget.
p95 under 50 ms, RAM budget of one machine.
The disk layout is computed over the whole dataset at build time, so continuous inserts erode it and performance decays gradually rather than breaking. And on network-attached storage the design collapses — per-read latency lands in the milliseconds and multiplies the ten-hop walk into something worse than the RAM index it replaced.
Why can you not just put HNSW on an SSD?
Explain DiskANN.
Is it safe to navigate on lossy vectors?
What is ScaNN doing that ordinary quantisation is not?
200 million vectors, 50 ms budget. What do you build?
How would you run this as a bake-off rather than an argument?
QIs DiskANN just HNSW on a disk?
No. HNSW moved verbatim to disk is about two hundred milliseconds a query. DiskANN changes two things — scoring served from compressed copies in RAM so a hop costs one read instead of thirty-three, and a flat graph with mixed-length edges so there are ~10 hops instead of 60. Without both changes it does not work.
QCan I run Vamana in memory, without the disk part?
Yes, and it works fine — a flat graph competing with HNSW on roughly equal terms. But the pairing is not accidental: the flat graph exists because sixty disk reads is unaffordable and ten is not. In RAM the motivation largely disappears.
QWhy is R usually larger than HNSW’s M?
Because the neighbour list is read from disk in one 4 KB page regardless of how full it is. You are paying for the page, so you may as well use it. In RAM there is no such quantum — a bigger M costs proportionally more memory.
QDoes DiskANN need an NVMe drive specifically?
It needs per-read latency near a hundred microseconds and enough IOPS for your concurrency. Local NVMe delivers that; a spinning disk does not come close; and network-attached storage typically lands in milliseconds, which multiplies the ten-hop walk into something worse than the RAM index it replaced.
QIs ScaNN a competitor to HNSW?
Not really, and it is worth saying so rather than treating all five as alternatives. ScaNN is a partition-based system whose distinctive contribution is a better quantisation objective, and its ideas compose with other structures rather than replacing them.
QCan I combine quantisation with any of these?
Yes, everything except flat — which is why vendor names run together (IVF-PQ, HNSW-SQ). Quantisation is not an index type; it is orthogonal to the structure. It helps partition-based indexes more than graph ones, because sequential scanning is bandwidth-bound and random access is latency-bound.
QWhat if my corpus is 30 million vectors — right in the gap?
Do the RAM arithmetic first, because it usually decides for you. 30M at 768-d is ~92 GB of vectors plus ~8 GB of graph — fits on a large machine, uncomfortable on three medium ones. If it nearly fits, reduce the dimension or the precision first: a cheaper lever than changing index type.
QHow do I benchmark these fairly?
Fix the recall target, then measure everything else at that recall. A latency comparison at unspecified recall is meaningless, and it is the most common flaw in published benchmarks. Use your own corpus and query mix, include the filters, and measure build and rebuild time as well as query time.
The interesting part of DiskANN is not the disk — it is where the approximation is allowed to live. Errors during navigation are self-correcting: pick the second-best neighbour and the next hop fixes it. Errors in the final ranking are not: that goes to a user and nothing downstream catches it. So the design puts lossy compressed vectors entirely in the first job and full precision entirely in the second — and ScaNN is the same instinct applied to the compression itself, placing the error sideways where a dot product cannot see it.
How many vectors, at what dimension — what is the RAM number?
What is the latency budget, as a number, and how much are you using now?
Is the storage local NVMe, or network-attached?
Is the corpus rebuilt in bulk or edited continuously?
Is there a filter on every query?
Was the last benchmark run at a fixed recall target?