LLM Inference Math · 4 of 4L2algorithms
Vector Indexes: The Recall-vs-Latency Trade-off of HNSW and IVF
Why approximate nearest-neighbour search is a dial between how many true neighbours you find and how long you wait, and how HNSW and IVF set that dial.
Abstract
Retrieval over embeddings turns a semantic query into a nearest-neighbour search in a high-dimensional vector space, and at scale an exact search is too slow to serve. Approximate nearest-neighbour indexes trade a controlled loss of correctness for a large gain in speed, and the entire engineering problem is understanding that trade. This piece defines recall and latency precisely, derives the cost model of the two dominant index families, the inverted file (IVF) and the hierarchical navigable small-world graph (HNSW), and shows that each exposes a single knob that moves you along a recall-latency Pareto frontier. It ends with why the last few points of recall cost the most and where the whole approach degrades.
Semantic retrieval rests on a simple idea: encode text as a vector so that meaning becomes geometry, and finding relevant documents becomes finding nearby points. The trouble is that finding the truly nearest points among hundreds of millions of vectors, exactly, means comparing the query against every one of them, and that linear scan is far too slow to sit in the path of a live request. Approximate nearest-neighbour search resolves this by giving up exactness on purpose: it returns the true neighbours most of the time, and in exchange it runs orders of magnitude faster. How often it is right is called recall, how long it takes is latency, and every vector index is fundamentally a machine for trading one against the other. Understanding that trade, and the two index families that dominate it, is the whole game.
The problem and its exact cost
State the task precisely. Given a database of N vectors in d dimensions and a query vector, return the k database vectors closest to the query under a distance such as Euclidean distance or cosine similarity. This is the k-nearest-neighbour problem, and the embeddings themselves come from models such as the transformer (Vaswani et al., 2017), which map text to vectors whose geometric proximity approximates semantic similarity.
The exact solution is a brute-force scan: compute the distance from the query to all N vectors and keep the smallest k. Each distance is order d work, so a single query costs order N times d operations. At a hundred million vectors of a thousand dimensions that is a hundred billion multiply-adds per query, which no interactive service can afford. The exactness is not the problem; the linear dependence on N is.
Approximate nearest-neighbour search breaks that linear dependence by not looking at every vector. It builds an index once, offline, that lets a query examine only a small, cleverly chosen subset of the database, at the price of occasionally missing a true neighbour.
Recall and latency, defined
The correctness metric is recall at k. Let the true set of k nearest neighbours be known (computed by exact search on a sample). Recall at k is the fraction of that true set that the approximate index actually returns. A recall of 0.95 means that, on average, nineteen of every twenty true neighbours are found; the twentieth is replaced by something slightly farther away. Recall is a property of the whole query distribution, so it is always reported as an average over a representative query set.
The cost metric is latency: the wall-clock time to answer one query, which in these indexes is dominated by the number of database vectors whose distance the search actually computes. Call that the number of candidates examined; latency is essentially that count times the per-distance cost d, plus index-traversal overhead.
The central fact is that these two move together. Every index has a parameter that, when increased, makes the search examine more candidates: recall rises toward one, and latency rises with it. You are never choosing recall or latency in isolation; you are choosing a point on a curve that relates them.
IVF: partition, then probe a few cells
The inverted file index reduces candidates by geography. Offline, cluster the database vectors into a set of cells, typically by running k-means to find a number of centroids; each vector is assigned to its nearest centroid, forming an inverted list per cell. At query time, compute the distance from the query to the centroids, pick the few nearest cells, and scan only the vectors in those cells. The number of cells you probe is the knob, conventionally called n_probe.
The cost model is direct. With the database split into roughly equal cells, each cell holds about N over the number-of-cells vectors, so probing n_probe cells examines about n_probe times that many candidates. Latency therefore scales linearly with n_probe. Recall rises with n_probe too, because a true neighbour is found only if its cell is among those probed; probe more cells and you are less likely to miss the cell a neighbour lives in.
The failure this exposes is the boundary problem: a true neighbour that happens to sit just across a cell boundary from the query is missed unless you probe its neighbouring cell. That is exactly why recall climbs with n_probe, and why IVF alone rarely reaches the very highest recalls without probing so many cells that its speed advantage erodes.
HNSW: walk a small-world graph
The hierarchical navigable small-world graph (Malkov & Yashunin, 2018) reduces candidates by navigation instead of partition. It builds a proximity graph in which each vector is a node linked to a bounded number of near neighbours, and it stacks several such graphs in layers: a sparse top layer for long jumps and progressively denser layers below, ending in a bottom layer that contains every vector. A search enters at the top, greedily walks toward the query until it can get no closer, drops a layer, and repeats.
The layered structure is what gives the method its speed. The long-range links in the upper layers let the search cross the space in a few hops, so the expected number of steps grows only logarithmically with the database size, echoing the small-world property that any two nodes are connected by a short path. The knob is the search beam width, conventionally efSearch: the number of best candidates the greedy walk keeps as it explores. A wider beam explores more of the graph, finds more true neighbours, and costs proportionally more.
So HNSW and IVF arrive at the same trade from opposite directions: IVF widens the search by probing more cells, HNSW by keeping a wider beam. Both dials increase candidates examined, and both push recall and latency up together.
The Pareto frontier
Sweep the knob of any one index and you trace a curve of recall against latency. That curve is a Pareto frontier: for a given index and dataset, it is the best recall achievable at each latency, and no setting lets you beat it on both axes at once. Comparing indexes means comparing frontiers, not single points; one index dominates another only if its whole curve sits above and to the left.
The frontier is concave and saturating. Early on, spending a little more latency buys a lot of recall, because the first extra candidates examined are the ones most likely to contain missed neighbours. As recall approaches one, the curve flattens: the remaining misses are the genuinely hard cases, neighbours hidden across a cell boundary or behind a poor graph link, and dislodging each one costs a disproportionate number of extra candidates. The last few points of recall are the most expensive latency you will ever buy.
This shape is why the right question is never 'what is the fastest index' or 'what is the most accurate' but 'what recall does the application actually need, and what is the cheapest latency that reaches it'. A retrieval-augmented system that tolerates a 95 percent recall can run many times faster than one that insists on 99.9.
Memory is the third axis
Recall and latency are the visible trade, but memory is a silent third axis that often decides the choice. HNSW stores an explicit graph: every node keeps links to a bounded number of neighbours, so the index adds memory proportional to that degree times the number of vectors, on top of the vectors themselves. That overhead is what buys its excellent frontier, and it is why HNSW is memory-hungry at billion-vector scale.
IVF stores only cell assignments and centroids, so its index overhead is small, but it is frequently paired with vector compression to shrink the vectors themselves. Product quantization replaces each vector with a compact code, cutting memory by an order of magnitude at the cost of approximate distances. This is the same lossy-compression trade studied for model weights, where post-training quantization such as AWQ (Lin et al., 2023) trades a controlled numerical error for a large memory saving; here the error lands in the distance estimates and therefore in recall, an equivalence I draw as my own synthesis rather than a claim from that work.
The practical consequence is that the index decision is three-dimensional. In systems where memory is plentiful, HNSW usually offers the best recall-latency frontier; where memory is the binding constraint, IVF with compression trades some frontier quality for a much smaller footprint, and the serving stack (Kwon et al., 2023, on memory-efficient LLM serving) has to budget for whichever index it chooses alongside the model.
When it breaks
First, the saturation wall. Because the frontier flattens near recall one, any requirement for near-perfect recall forces latencies that approach the exact scan you were trying to avoid. If an application genuinely needs every true neighbour, approximate search is the wrong tool and exact or hybrid methods should be considered instead.
Second, dimensionality. As d grows, distances between points concentrate and the geometric signal that both partitioning and graph navigation rely on weakens, the familiar curse of dimensionality. Very high-dimensional embeddings make cells less discriminative and graph links less informative, pushing every index's frontier downward; dimensionality reduction before indexing is often the real fix.
Third, distribution shift and structure. The index is built from the database distribution, so queries that fall in sparse regions, or a database with strong hubness where a few vectors are everyone's neighbour, degrade recall unpredictably. And the frontier is measured on a query sample: if production queries differ from that sample, the recall you validated is not the recall you get. The defensive posture is to measure recall continuously on live-like queries and to choose the knob from the application's true recall requirement, not a default.
Key takeaways
- Exact nearest-neighbour search costs order N times d per query; approximate indexes break that linear dependence by examining only a small subset of vectors.
- Recall at k is the fraction of true neighbours returned; latency is dominated by the number of candidate vectors whose distance is computed. They rise together.
- IVF partitions vectors into cells and probes the n_probe nearest; candidates and latency scale linearly with n_probe, and recall rises because fewer true neighbours are missed across cell boundaries.
- HNSW walks a layered small-world proximity graph in about log N hops; the search beam width efSearch is its recall-latency knob.
- Sweeping either knob traces a concave, saturating recall-latency Pareto frontier; the last points of recall are by far the most expensive latency.
- Memory is a third axis: HNSW stores an explicit graph and is memory-hungry, while IVF plus product quantization trades frontier quality for a much smaller footprint.
- The approach breaks near perfect recall, in very high dimensions, and under query distribution shift; choose the knob from the application's true recall requirement.
Practitioner Toolkit
Copy-paste, strictly defensive artifacts you can use today. Nothing here attacks a real system.
Decide these before picking IVF or HNSW.
- State the recall target the application actually needs (e.g. recall@10 >= 0.95), not a default.
- Estimate N, d, and the memory budget for the index on top of the vectors.
- If memory is plentiful, benchmark HNSW; if it is the binding constraint, benchmark IVF plus product quantization.
- Sweep the knob (n_probe or efSearch) and record the recall-latency frontier on representative queries.
- Pick the smallest knob value that meets the recall target, then leave headroom for query drift.
Measure the curve instead of trusting defaults.
truth = exact_knn(queries, database, k) # offline ground truth
for knob in knob_values: # n_probe for IVF, efSearch for HNSW
index.set_search_param(knob)
t0 = now(); results = index.search(queries, k); t = now() - t0
recall = mean(overlap(results[i], truth[i]) / k for i in queries)
report(knob, recall, latency = t / len(queries))
# choose the smallest knob whose recall >= targetDo these first, in order.
- Start with HNSW at a moderate efSearch if memory allows; it usually has the best frontier.
- Measure recall@k on a held-out query set before trusting the index.
- If the footprint is too large, switch to IVF with product quantization and re-measure.
- Reduce embedding dimensionality before indexing if recall is stubbornly low.
Glossary
- Approximate nearest-neighbour search
- Finding the closest database vectors to a query while allowing a controlled chance of missing some, in exchange for far lower cost than an exact scan.
- Recall at k
- The fraction of the true k nearest neighbours that an approximate search actually returns, averaged over queries.
- IVF (inverted file index)
- An index that clusters vectors into cells and, at query time, scans only the few cells nearest the query.
- n_probe
- The number of IVF cells a query scans; raising it increases both recall and latency.
- HNSW
- A hierarchical navigable small-world graph index that searches a layered proximity graph in roughly logarithmic hops.
- efSearch
- The beam width of an HNSW search; a wider beam explores more of the graph, raising recall and latency.
- Pareto frontier
- The set of best recall values achievable at each latency for a given index and dataset; comparing indexes means comparing frontiers.
References
- Malkov & Yashunin (2018), Efficient and robust approximate nearest neighbor search using Hierarchical Navigable Small World graphs (IEEE TPAMI)
- Vaswani et al. (2017), Attention Is All You Need (NeurIPS)
- Lin et al. (2023), AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration
- Kwon et al. (2023), Efficient Memory Management for LLM Serving with PagedAttention (SOSP)