Vector Databases / Indexing
Why a WHERE clause cannot find nearest neighbors.
Reviewed by Yuvaraj
You have already turned your documents into embeddings: millions of dense vectors, each a few hundred numbers that capture meaning. Now a user query arrives, you embed it too, and you need the handful of stored vectors closest to it, its nearest neighbors, in milliseconds, while new vectors keep streaming in. That single requirement is what a vector database exists to solve. It is not merely a place to keep vectors; it is a system built around the one query that dominates semantic search: "which of my millions of vectors are most similar to this one?"
Exact k-nearest-neighbor search compares the query against every stored vector, computing a similarity for each. With vectors of dimension , that is work per query. For a few thousand vectors this is trivial and you should just do it, a NumPy dot product or a single SQL scan is genuinely fine. The problem is linear growth: ten thousand vectors returns instantly, ten million does not.
N = 10,000,000 vectors, d = 768 dimensions, FP32 (4 bytes/number)
Brute force, per query:
distance ops = N * d = 10^7 * 768 ≈ 7.7 x 10^9 multiply-adds
memory read = N * d * 4B = 3.07 x 10^10 ≈ 30 GB scanned per query
at ~30 GB/s memory bandwidth ≈ 1 second PER QUERY
ANN index (e.g. HNSW), per query:
candidates visited ≈ 5,000 vectors
distance ops = 5,000 * 768 ≈ 3.8 x 10^6 multiply-adds
~2000x fewer operations ≈ single-digit milliseconds
Ask about this lesson, or about anything in AI. Answers cite the lessons they draw on.
Finished this lesson?
Mark it complete to earn XP, keep your streak, and schedule a review.
Exact search must read every vector, roughly 30 GB, for a single query, taking on the order of a second before you have even served a second user. An approximate-nearest-neighbor (ANN) index instead navigates a precomputed structure straight to a small neighborhood, comparing only a few thousand candidates: about 2000x fewer operations, turning seconds into milliseconds. That order-of-magnitude gap is the entire reason ANN indexes, and the databases built around them, exist.
An ANN algorithm alone gives you fast approximate search, but a production system needs far more: durable persistence, insert/update/delete without rebuilding the whole index, metadata stored beside each vector so you can filter (by tenant, date, or permission), horizontal scaling across machines, replication, backups, and safe concurrent reads and writes. Where those concerns live is the practical difference between the three things people loosely call "vector search."
| Concern | In-process library (FAISS) | Vector-capable extension (pgvector) | Dedicated vector DB (Pinecone, Qdrant, Weaviate, Milvus) |
|---|---|---|---|
| Persistence | You manage index files yourself | Yes, via Postgres storage | Yes, managed for you |
| CRUD / upserts | Often needs a full rebuild | SQL INSERT / UPDATE / DELETE | First-class upsert API |
| Metadata filtering | Not built in | SQL WHERE and joins | Native filtered search |
| Horizontal scaling | None (single process) | Postgres replicas / sharding | Built-in sharding and replication |
| Best when | Prototyping, embedded in one app | You already run Postgres, moderate scale | Millions+ vectors, high QPS, ops offloaded |
For a curious beginner
How it is actually used
ef_search in HNSW, nprobe in IVF, the number of graph links per node. You pick a target such as "95% recall at a 5 ms p99 latency," tune until you hit it, then re-check after your data grows.The underlying mechanism
Common mistakes