Vector Databases: The High-Dimensional Indexing You Actually Need
A deep dive into vector embeddings, vector databases, and indexing algorithms like IVF and HNSW.
Vector Databases: The High-Dimensional Indexing You Actually Need
Your traditional relational or document database is exceptional at filtering on exact values and structured metadata, but it falters when asked “find me things that are semantically similar to this.” This is the domain of vector embeddings, and by extension, vector databases, which are purpose-built to index and query these high-dimensional representations of your data at scale. They are the critical infrastructure powering modern RAG pipelines, recommendation engines, and image search systems.
What you’ll walk away with:
- A clear mental model of the vector search data flow, from ingestion to query.
- The ability to choose the right vector database approach for your workload.
- A deep understanding of the trade-offs between the two most common indexing algorithms: IVF and HNSW.
- A practical checklist for evaluating and implementing a vector search solution.
The Core Architecture of Vector Search
At its heart, a vector database doesn’t replace your primary datastore; it augments it. It solves one problem exceptionally well: finding the “nearest” vectors to a query vector from a collection of millions or billions, in milliseconds. The overall process involves two distinct flows: ingestion and query.
Here is a high-level view of the entire lifecycle:
flowchart TD
subgraph Ingestion Pipeline
direction LR
A[Unstructured Data <br/>(text, image, audio)] --> B{Embedding Model <br/>(e.g., BERT, CLIP)};
B --> C["Vector Embedding <br/>(e.g., 768-dim float array)"];
C --> D[Vector Database];
D -- "Stores Vector + Metadata/ID" --> D;
end
subgraph Query Pipeline
direction LR
E[User Query <br/>(e.g., "blue sneakers") ] --> F{Embedding Model};
F --> G["Query Vector"];
G --> H[Vector Database];
H -- "Performs ANN Search" --> I["Top-K Results <br/>(IDs of nearest vectors)"];
end
I --> J{Application Logic};
J -- "Fetches full data from <br/>primary DB using IDs" --> K[Primary Datastore <br/>(Postgres, Mongo, etc.)];
K --> J;
J --> L[Final Response];
The magic happens inside the “Vector Database” box. Instead of B-Trees or inverted text indexes, it uses specialized Approximate Nearest Neighbor (ANN) algorithms to avoid a brute-force (and computationally impossible) search across the entire dataset.
Example: Generating an Embedding with Python
Here’s a minimal example of creating a vector embedding from a sentence using the sentence-transformers library. This is the vector that you would ingest into the database.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from sentence_transformers import SentenceTransformer
# Load a pre-trained model
model = SentenceTransformer('all-MiniLM-L6-v2')
sentences = [
"The engineer debugged the code.",
"A chef prepares a delicious meal."
]
# Generate embeddings
embeddings = model.encode(sentences)
# The first vector has 384 dimensions
print(embeddings[0].shape)
print(embeddings[0][:5]) # Print first 5 dimensions
The output shows the dimensionality and a sample of the vector’s values.
1
2
(384,)
[ 0.05380507 -0.03335503 0.0389311 -0.01025531 0.07008719]
Choosing Your Path: Dedicated DB vs. Augmented System
Not every project requires a standalone, managed vector database. Your existing infrastructure might be sufficient, especially for smaller-scale projects or proofs-of-concept. Use this flowchart to guide your decision.
graph TD
A{Start: Do you need<br/>vector search?} --> B{Is your dataset >10M vectors<br/>and growing fast?};
B -- Yes --> C["A dedicated vector DB is likely necessary <br/> for performance and scalability."];
B -- No --> D{Are you heavily invested in<br/>Postgres and your team has deep expertise?};
D -- Yes --> E{Try `pgvector`.};
E -- "Can it meet latency SLOs<br/>under load?" --> F[Yes: Stick with it.];
E -- "Can it meet latency SLOs<br/>under load?" -- No --> G["Re-evaluate: A dedicated DB or <br/>Elasticsearch may be better."];
D -- No --> H{Do you primarily need hybrid search<br/>(keyword + vector) on text data?};
H -- Yes --> I["Elasticsearch or OpenSearch with k-NN<br/>is a strong contender."];
H -- No --> J["A dedicated vector DB offers the best<br/>performance for pure vector workloads."];
This decision isn’t just about performance; it’s about operational overhead. Augmenting Postgres with pgvector keeps your stack simple, while a dedicated database introduces another component to manage, monitor, and scale.
A Tale of Two Indexes: IVF vs. HNSW
The performance of your vector database hinges almost entirely on its indexing strategy. The two dominant algorithms you’ll encounter are Inverted File (IVF) and Hierarchical Navigable Small World (HNSW). They represent a fundamental trade-off between build time, memory usage, and query speed.
| Feature | Inverted File (IVF) | Hierarchical Navigable Small World (HNSW) |
|---|---|---|
| Core Idea | Partitions the vector space into clusters using k-means. A query only searches a few nearby clusters (nprobe). |
Builds a multi-layered proximity graph. A query traverses the graph from a coarse top layer to a fine bottom layer. |
| Index Build Time | Fast. Relatively simple clustering process. | Slow. Constructing the complex, layered graph is computationally expensive. |
| Query Speed | Fast. The search space is dramatically reduced to a few clusters. | Very Fast. Graph traversal is highly efficient for finding nearest neighbors. |
| Memory Usage | Moderate. Stores cluster centroids and vector assignments. | High. Must store the entire graph structure in memory for low-latency access. |
| Recall / Accuracy | Good. Tunable by increasing the nprobe parameter (how many clusters to search). |
Excellent. Tunable by increasing the search scope (ef_search) during traversal. |
| Data Updates | Difficult. Adding new vectors is easy, but they won’t be indexed until the clusters are rebuilt. Deletes are costly. | Easier. Vectors can be added and “deleted” (marked as removed) online, though performance can degrade over time. |
| Best For… | Static or batch-updated datasets where build time is a concern. Good for memory-constrained environments. | Dynamic, real-time applications with high query throughput and strict latency requirements. |
The dimensionality of your vectors (e.g., 384, 768, 1536) has a huge impact on index size and search performance. Always start with a lower-dimension model if it meets your accuracy needs.
Conceptually, the shift from keyword to vector search changes how we write queries.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
--- a/keyword_search_logic.sql
+++ b/vector_search_logic.py
@@ -1,3 +1,6 @@
-SELECT product_id, product_name
-FROM products
-WHERE product_description LIKE '%running shoe for trails%';
+query_vector = embedding_model.encode("running shoe for trails")
+
+results = vector_db_client.search(
+ collection_name="products",
+ query_vector=query_vector,
+ limit=10
+)
The “before” is a brittle pattern match. The “after” finds results based on conceptual meaning, not just shared words.
Implementation Checklist
Before you commit to a solution, run through this checklist to ensure you’ve covered the key considerations.
- Benchmark Models: Have you tested different embedding models? A smaller, faster model might be sufficient.
- Define SLOs: What is your required P95 query latency? How high is your query throughput (QPS)?
-
Evaluate Metadata Filtering: Do you need to pre-filter candidates based on metadata (e.g.,
category = 'footwear') before the vector search? Check if your chosen solution supports this efficiently. - Estimate Costs: Calculate the total cost of ownership, including hosting/licensing, data transfer, and operational overhead.
- Prototype a Hybrid Approach: If applicable, build a small PoC that combines keyword search for filtering and vector search for semantic ranking.
- Plan for Re-indexing: How will you handle model updates? All existing vectors must be re-generated and re-indexed when you switch to a new embedding model.
Choosing the right vector database is a significant architectural decision. By understanding the core trade-offs in indexing and aligning them with your specific product requirements, you can build a robust and scalable similarity search system.
FAQ
Q: What is the difference between a vector database and Postgres with a JSONB column?
A: The key difference is the specialized indexing. A JSONB column allows you to store a vector (as an array), but you can’t create an index for efficient similarity search. A query would require a full table scan, calculating the distance between your query vector and every single row, which is unfeasible at any scale.
Q: How do I choose the right vector dimension size?
A: This is a trade-off. Higher dimensions (e.g., 1536) can capture more nuance and provide better accuracy, but they require more storage, more memory for indexing, and can be slower to query. Start with a well-regarded model in a lower-dimensional space (e.g., 384 or 768) and only increase it if your offline evaluations show a significant accuracy improvement.
Q: Can I use a vector database for exact nearest neighbor search?
A: Yes, you can force most systems to perform an exact, brute-force search by not using an index. However, this completely defeats the purpose of using a vector database. The entire value proposition is based on Approximate Nearest Neighbor (ANN) search, which sacrifices perfect accuracy for massive gains in speed.
Found an error or outdated command? Edit this page on GitHub or open an issue.
