HNSW IndexΒΆ
Hierarchical Navigable Small World (HNSW) is the default index type in GoVector, providing efficient approximate nearest neighbor (ANN) search. This document explains how HNSW works and how to optimize it for your use case.
π HNSW OverviewΒΆ
HNSW is a state-of-the-art approximate nearest neighbor search algorithm that:
- Provides high recall (close to 100% for well-tuned parameters)
- Offers fast search performance (O(log N) complexity)
- Scales well with high-dimensional vectors (up to thousands of dimensions)
- Supports dynamic insertion of new vectors
π§ HNSW ParametersΒΆ
Core ParametersΒΆ
| Parameter | Description | Default | Range | Impact |
|---|---|---|---|---|
M |
Number of connections per node | 16 | 4-64 | Higher values increase accuracy and memory usage |
EfConstruction |
Size of the dynamic candidate list during index construction | 200 | 10-β | Higher values improve index quality but increase build time |
EfSearch |
Size of the dynamic candidate list during search | 10 | 10-β | Higher values improve recall but increase search time |
π Creating an HNSW IndexΒΆ
Embedded ModeΒΆ
import (
"github.com/yourusername/govector/core"
)
// Create a collection with HNSW index
collection, err := core.NewCollection(core.CollectionConfig{
Name: "my-collection",
VectorLen: 768,
Metric: core.Cosine,
IndexType: core.HNSW, // Use HNSW index
M: 16, // Number of connections per node
EfConstruction: 200, // Construction parameter
EfSearch: 10, // Search parameter
})
if err != nil {
log.Fatalf("Failed to create collection: %v", err)
}
Microservice ModeΒΆ
curl -X POST http://localhost:6333/collections \
-H "Content-Type: application/json" \
-d '{
"name": "my-collection",
"vectors": {
"size": 768,
"distance": "Cosine"
},
"hnsw_config": {
"m": 16,
"ef_construction": 200,
"ef": 10
}
}'
π How HNSW WorksΒΆ
HNSW creates a multi-layered graph structure where:
- Each layer is a navigable small world graph
- Higher layers act as coarse guides to lower layers
- Search starts at the top layer and navigates down to find nearest neighbors
- Insertion follows a similar path, building connections at each level
Search ProcessΒΆ
flowchart TD
A[Start at top layer] --> B[Find nearest neighbor in current layer]
B --> C{Is current layer the bottom?}
C -->|No| D[Move to next lower layer]
D --> B
C -->|Yes| E[Return nearest neighbors]
Insertion ProcessΒΆ
flowchart TD
A[Start at top layer] --> B[Find nearest neighbors in current layer]
B --> C{Is current layer the bottom?}
C -->|No| D[Move to next lower layer]
D --> B
C -->|Yes| E[Insert node and build connections]
E --> F[Potentially add node to higher layers]
π‘ Optimization TipsΒΆ
For Large DatasetsΒΆ
- Increase
Mto 24-32 for higher recall - Increase
EfConstructionto 400-1000 for better index quality - Use
EfSearchbetween 50-100 for high recall applications - Enable SQ8 quantization to reduce memory usage
For Fast SearchΒΆ
- Decrease
Mto 8-12 for faster indexing and lower memory usage - Set
EfSearchto 10-20 for faster search (trading off recall) - Use smaller vectors when possible (e.g., 384 dimensions instead of 768)
For Memory ConstraintsΒΆ
- Enable SQ8 quantization to reduce memory by ~75%
- Use smaller
Mvalues (8-12) - Consider Flat index for very small datasets (< 10,000 points)
π Performance BenchmarksΒΆ
Search PerformanceΒΆ
| Dataset Size | M | EfSearch | Recall | QPS |
|---|---|---|---|---|
| 100K points | 16 | 10 | ~0.9 | 10,000+ |
| 100K points | 16 | 50 | ~0.95 | 5,000+ |
| 100K points | 16 | 100 | ~0.99 | 2,000+ |
| 1M points | 16 | 10 | ~0.85 | 5,000+ |
| 1M points | 16 | 50 | ~0.9 | 2,000+ |
| 1M points | 16 | 100 | ~0.95 | 1,000+ |
Memory UsageΒΆ
| Dataset Size | Vector Dim | M | Memory (no quantization) | Memory (with SQ8) |
|---|---|---|---|---|
| 100K points | 768 | 16 | ~1GB | ~250MB |
| 1M points | 768 | 16 | ~10GB | ~2.5GB |
| 10M points | 768 | 16 | ~100GB | ~25GB |
π© Common IssuesΒΆ
Slow Index BuildΒΆ
- Cause: High
EfConstructionvalue or large dataset - Solution: Use appropriate
EfConstructionfor dataset size, consider batch insertion
Low RecallΒΆ
- Cause: Low
EfSearchorMvalues - Solution: Increase
EfSearchfor search-time recall, increaseMfor index quality
High Memory UsageΒΆ
- Cause: Large
Mvalue or no quantization - Solution: Enable SQ8 quantization, reduce
Mvalue
π Related DocumentationΒΆ
- Collection Management - Collection creation and configuration
- Data Model - Core data structures
- Storage Engine - Persistence and serialization
- Usage Modes - Different ways to use GoVector