Choosing the right index type and tuning its parameters is critical for balancing search speed, recall accuracy, and memory usage. This guide covers the two dominant ANN (approximate nearest neighbor) algorithms: HNSW and IVFFlat.
| Property | HNSW | IVFFlat |
|---|---|---|
| Search speed | Very fast | Fast |
| Build speed | Slow | Fast |
| Memory usage | High (graph + vectors) | Medium (centroids + vectors) |
| Recall@10 | 95-99% | 85-95% |
| Update cost | Low (incremental) | High (re-clustering) |
| Best for | Most workloads | Large, static datasets |
HNSW (Hierarchical Navigable Small World) builds a multi-layer graph where each vector is a node connected to its nearest neighbours.
m (Graph Degree)Controls how many edges each node has. Higher m means better recall but more memory and slower inserts.
| m | Memory | Recall@10 | Insert Speed | Best For |
|---|---|---|---|---|
| 8 | Low | ~90% | Fast | Low-memory environments |
| 16 | Medium | ~95% | Medium | General purpose (recommended) |
| 32 | High | ~98% | Slow | High-recall requirements |
| 64 | Very high | ~99% | Very slow | Research / small datasets |
ef_construction (Build-Time Search Depth)Controls the quality of the graph during construction. Higher values produce better graphs but take longer to build.
| ef_construction | Build Time | Recall@10 | Recommendation |
|---|---|---|---|
| 64 | Fast | ~92% | Quick prototyping |
| 128 | Medium | ~95% | Good default |
| 200 | Slow | ~97% | Production (recommended) |
| 400 | Very slow | ~99% | Maximum quality |
ef_search (Query-Time Search Depth)Controls the depth of search at query time. Can be changed without rebuilding the index.
| ef_search | Latency | Recall@10 | Recommendation |
|---|---|---|---|
| 10 | Very fast | ~85% | Speed-critical applications |
| 50 | Fast | ~95% | Good default |
| 100 | Medium | ~98% | Production (recommended) |
| 200 | Slow | ~99% | Maximum recall |
IVFFlat (Inverted File with Flat quantization) partitions vectors into Voronoi cells using k-means clustering, then searches only the nearest cells.
lists (Number of Partitions)Controls how many Voronoi cells the vectors are divided into.
Rule of thumb: lists = sqrt(N) where N is the total number of vectors.
| N (vectors) | lists | nprobe | Recall@10 |
|---|---|---|---|
| 10,000 | 100 | 10 | ~95% |
| 100,000 | 316 | 20 | ~95% |
| 1,000,000 | 1,000 | 50 | ~95% |
nprobe (Query-Time Probes)Controls how many cells are searched at query time. Higher = better recall, slower search.
| nprobe / lists | Recall@10 | Speed |
|---|---|---|
| 1% | ~70% | Very fast |
| 5% | ~90% | Fast |
| 10% | ~95% | Medium (recommended) |
| 20% | ~98% | Slow |
Pinecone manages index parameters automatically. Choose between:
Default HNSW config works well. Key overrides:
{
"vectorIndexConfig": {
"ef": 100,
"efConstruction": 200,
"maxConnections": 16,
"distance": "cosine"
}
}Uses HNSW internally. Key settings:
collection = client.create_collection(
name="my_collection",
metadata={
"hnsw:space": "cosine",
"hnsw:M": 16,
"hnsw:construction_ef": 200,
"hnsw:search_ef": 100,
}
)Supports both HNSW and IVFFlat:
-- HNSW (recommended for most workloads)
CREATE INDEX ON items USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 200);
-- IVFFlat (for very large, static datasets)
CREATE INDEX ON items USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);
-- Set search-time parameters
SET hnsw.ef_search = 100;
SET ivfflat.probes = 10;Is your dataset static (rarely updated)?
├── YES
│ ├── Is memory constrained?
│ │ ├── YES → IVFFlat (lists=sqrt(N), nprobe=10%)
│ │ └── NO → HNSW (m=16, ef_construction=200)
│ └──
└── NO (frequent updates)
└── HNSW (m=16, ef_construction=200)
IVFFlat requires re-clustering on updates.