CSE Roadmap

Core tier · about 5 hours · 6 parts

Part 4 of 6 · 3 min read

pgvector and operating an index

The SQL shape, and what to choose and monitor.

pgvector in one page

If you already run Postgres, the pgvector extension adds a vector column type and ANN indexes. The shape is below. I have not run this against a database, so check each statement against the extension's documentation for the version you install.

CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE chunks (
  id        BIGSERIAL PRIMARY KEY,
  source    TEXT NOT NULL,
  heading   TEXT,
  body      TEXT NOT NULL,
  embedding VECTOR(1024) NOT NULL        -- must match your model's dimension
);

-- an approximate index (HNSW) using cosine distance
CREATE INDEX chunks_embedding_idx ON chunks
  USING hnsw (embedding vector_cosine_ops);

-- nearest 5 chunks to a query vector, with a metadata filter
SELECT id, source, heading, body
FROM chunks
WHERE source = 'manual-2026'
ORDER BY embedding <=> $1               -- <=> is cosine distance
LIMIT 5;

Points to remember: the vector size is fixed per column; the operator in the query must match the operator class in the index or the index is not used; and filtering plus approximate search can return fewer than k rows because the filter is applied to the candidates the index found. Test that case.

Choosing and operating an index

Situation Reasonable choice
Under about 100,000 vectors, one machine exact search (no index to tune)
Up to a few million, already on Postgres pgvector with HNSW
Very large, memory-bound IVF with compression, or a dedicated vector database
Frequent updates and deletes check how the index handles them before you commit (module 9)

Always keep: the model name and version that made the vectors, the dimension, and a copy of the original text. Vectors alone cannot be turned back into text.

Interview angle

"Why not just use exact search?" It is correct but costs time proportional to the collection for every query; ANN trades a small, measurable loss in recall for far less work. A strong answer names a family (IVF clusters or HNSW graphs), its main knob (nprobe or ef), how you would measure recall against exact search, and that the right target is end-to-end answer quality, not index recall alone. Mention that query and document vectors must come from the same model and that switching models means re-indexing.

Check yourself

Your index returns 10 results for the query "holiday opening" even though no document is about holidays. Why, and where should the fix go? (Nearest-neighbour search always returns k results. Add a score threshold or a refusal rule after retrieval, module 6.)

For the curious Two edge cases found in the example code

Searching an empty graph crashed with an IndexError, and asking IVF for more clusters than there are vectors crashed inside the random choice. The first now returns an empty list and the second raises a clear ValueError. Newer pgvector versions can also keep scanning when a filter removes many candidates; check your version's documentation instead of assuming the older behaviour.

What you will use daily at work

Practice What it looks like
A vector store with HNSW Postgres with pgvector, or a managed vector database; you set m, ef_construction and ef.
Recall against exact search Before trusting an index setting, compare it with brute force on a sample.
Storing model name and dimension Kept next to every vector so a model change is detected, not guessed.

Draft: confirm the vector store your team uses and its current index options.