Did you know · 1 min
Did you know pgvector ignores your index if the operator doesn't match?
An HNSW index built with vector_cosine_ops accelerates exactly one operator. Query with Euclidean distance instead and Postgres quietly scans every row — correct results, no error, and a query plan nobody looks at until the corpus grows.
Here is a fun way to have a vector index and not use it.
You build an HNSW index with vector_cosine_ops, because the tutorial did.
Then you query with <->, because that arrow looks like "distance" and the
query works. And it does work — correct rows, sensible order, no warning of any
kind. Postgres is just scanning every row in the table to produce them.
An HNSW index accelerates exactly one operator class: the one it was built
with. vector_cosine_ops serves <=> (cosine distance). vector_l2_ops
serves <-> (Euclidean). vector_ip_ops serves <#> (inner product). Mix
them and the planner does not error, does not warn, does not use the index. It
politely sequential-scans, which at ten thousand rows is a few milliseconds and
at a few million is your p99 falling over on a Tuesday.
This is the nastiest kind of bug — the kind that ships, because it is not wrong, only slow, and slow arrives months after the code review that approved it.
Thirty seconds of insurance: run EXPLAIN on your actual similarity query and
look for Index Scan using your index's name. If you see Seq Scan, your
operator and your opclass are not the pair you think they are. This site's own
retrieval uses <=> against a cosine index for exactly this reason — and yes,
we checked the plan.
In this article
The terms above, defined. New to this? Start here — nothing in the article assumes you already knew them.
- HNSW — hierarchical navigable small world Acronym ↩
A layered graph that finds near neighbours by entering at a sparse top layer and dropping down, checking a few hundred candidates instead of millions.
Not to be confused with exact search: Exact search compares every row and is always right. HNSW trades a small chance of missing the true nearest neighbour for an enormous speed gain.
- cosine similarity Definition ↩
A score from 0 to 1 for how closely two embeddings point in the same direction, where 1 is near-identical and 0 is unrelated.
Not to be confused with Euclidean distance: Cosine compares direction and ignores magnitude; Euclidean compares straight-line distance. An index built for one does not accelerate the other.