QUICK START:HTMLCSSJavaScriptTypeScriptPythonSQLReactNext.jsNode.jsLinux & UbuntuKotlinSwiftC# / .NETJavaGoRustC++DSASystem DesignDevOpsCybersecurityAI / ML
Advanced 28 min readModule: Module 14: Vector Databases: HNSW & IVF-PQ Indexing

Vector Database Internals: HNSW & IVF-PQ Indexing

Deconstruct production Vector Databases (Milvus, Pinecone, Qdrant, pgvector): Approximate Nearest Neighbor (ANN) search, Hierarchical Navigable Small World (HNSW multi-layer graphs), Product Quantization (PQ sub-vector compression), and SIMD-accelerated distance metrics.

What You Will Learn in This Lesson

  • Why brute-force Exact Nearest Neighbor (kNN) search O(N * D) fails on millions of high-dimensional embeddings
  • The Hierarchical Navigable Small World (HNSW) graph: multi-layer skip-list inspired graph navigation in O(log N)
  • Inverted File Index with Product Quantization (IVF-PQ): compressing 1536-dimensional vectors by 95%
  • Filtering with vector payload metadata: Pre-filtering vs Post-filtering vs Single-Stage HNSW Filter Graphs

Introduction & Core Concept

Generating 1536-dimensional OpenAI embeddings is only the first step. When a database contains 10,000,000 document vectors, calculating exact Euclidean distance or Cosine Similarity across every vector takes several seconds per query. Vector databases achieve sub-millisecond retrieval across billions of vectors using Approximate Nearest Neighbor (ANN) data structures, primarily Hierarchical Navigable Small World (HNSW) graphs.
WHY DOES THIS MATTER IN THE REAL WORLD?

High-scale RAG systems, visual search engines, and recommendation systems (Spotify, Pinterest) serve real-time semantic queries in under 5ms using HNSW and IVF-PQ indexing.

Syntax & Structure

python
// pgvector HNSW Index Creation
CREATE INDEX ON document_embeddings
USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 64);

Simulating HNSW Multi-Layer Graph Skip-Navigation in Python

python
python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# Hierarchical Navigable Small World (HNSW) Conceptual Graph Navigation
import numpy as np
class HNSWLayerNode:
def __init__(self, vector_id, vector):
self.id = vector_id
self.vector = vector
self.neighbors = [] # Connected edge pointers
def cosine_similarity(v1, v2):
return np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2) + 1e-9)
class SimpleHNSW:
def __init__(self):
# Layer 1 (Top sparse layer: long skips) and Layer 0 (Bottom dense layer: exact local search)
self.layer1_nodes = []
self.layer0_nodes = []
def search_layer(self, query_vec, entry_node, candidate_pool_size=4):
"""Greedy graph search on a single layer: Move to closest neighbor until local minima."""
current = entry_node
best_sim = cosine_similarity(query_vec, current.vector)
while True:
improved = False
for neighbor in current.neighbors:
sim = cosine_similarity(query_vec, neighbor.vector)
if sim > best_sim:
best_sim = sim
current = neighbor
improved = True
if not improved:
break # Local maximum similarity reached on this layer!
return current, best_sim
# Create simulated nodes
node_a = HNSWLayerNode("Doc_Tech", np.array([0.9, 0.1, 0.2]))
node_b = HNSWLayerNode("Doc_Science", np.array([0.8, 0.3, 0.1]))
node_c = HNSWLayerNode("Doc_Cooking", np.array([0.1, 0.9, 0.8]))
node_a.neighbors = [node_b]
node_b.neighbors = [node_a, node_c]
node_c.neighbors = [node_b]
hnsw = SimpleHNSW()
query = np.array([0.95, 0.05, 0.15]) # Search query close to Tech
best_match, score = hnsw.search_layer(query, entry_node=node_c) # Start from distant entry node
print("=== HNSW Vector Database Search Engine ===")
print(f"Top Semantic Match: {best_match.id} (Cosine Similarity: {score:.4f})")
print("✅ Graph navigated via Small-World links to target in logarithmic O(log N) hops!")

Line-by-Line Technical Breakdown

1Product Quantization (PQ): A 1536-dimension float32 vector consumes 6,144 bytes of RAM. Product Quantization splits the vector into 64 sub-vectors of 24 dimensions, clusters each sub-vector into 256 centroids (1 byte codebook index), compressing the vector from 6KB down to 64 bytes (99% RAM savings) with hardware AVX SIMD asymmetric distance lookup.

Try It Yourself (Interactive Editor)

Modify the code in real-time and click Run to test live browser output and console logs.

Intelligent Code Runner & Live Sandbox[PYTHON]
PYTHON SOURCE EDITOR
Interactive Live Code

Common Mistakes & How to Avoid Them

#1: Filtering vector search queries using naive post-filtering (fetching top 10 vectors then filtering by user ID), returning 0 results if all 10 belong to other users.

Post-filtering suffers from severe recall collapse. Always use vector databases that support single-stage filtered graph traversal.

Incorrect / Antipattern
// Step 1: kNN search top 10 -> Step 2: filter(user_id == '123') -> Empty list!
Correct / Professional Solution
// Use Single-Stage Iterative HNSW Filtering (Qdrant / Milvus) to traverse filtered graph edges

Industry Best Practices & Professional Standards

  • Tune HNSW parameters: `M = 16-32` (connections per node) and `ef_construction = 64-128` (build index accuracy).
  • Use Product Quantization (IVF-PQ) when indexing datasets exceeding 50,000,000 vectors on limited RAM.
  • Normalize vectors to unit length during ingestion to turn Dot Product into fast Cosine Similarity.

Lesson Summary & Core Takeaways

  • HNSW constructs multi-layer proximity graphs for sub-millisecond O(log N) vector retrieval.
  • Product Quantization (PQ) compresses multi-dimensional vectors by up to 95%.
  • Single-stage filtered traversal prevents recall degradation in multi-tenant RAG applications.