Product Quantization Integration Guide
Product Quantization Integration Guide
Overview
Product Quantization (PQ) is now fully integrated with HeliosDB Nano’s storage layer, enabling memory-efficient vector indexing with 8-16x compression while maintaining 95-98% search accuracy.
Features
- SQL Support: Create PQ indexes using standard SQL syntax
- Automatic Configuration: Smart defaults based on vector dimensions
- Persistence: Codebooks and quantized vectors are fully persisted
- Transparency: Works seamlessly with existing vector operations
SQL Syntax
Basic PQ Index Creation
-- Create table with vector columnCREATE TABLE documents ( id INTEGER PRIMARY KEY, title TEXT, embedding VECTOR(768));
-- Create PQ-compressed vector indexCREATE INDEX doc_embedding_idx ON documents(embedding)USING hnswWITH (quantization='product');Advanced Configuration
-- Customize PQ parametersCREATE INDEX custom_pq_idx ON documents(embedding)USING hnswWITH ( quantization='product', pq_subquantizers=8, -- Number of sub-quantizers (M) pq_centroids=256 -- Centroids per sub-quantizer (K));Parameter Guidelines
pq_subquantizers (M):
- Default: Auto-calculated based on dimension
- 768+ dims: M=8
- 256-767 dims: M=4
- <256 dims: M=2
- Must evenly divide vector dimension
- Higher M = better accuracy, larger codes
- Typical range: 2-16
pq_centroids (K):
- Default: 256 (recommended)
- Range: 1-256
- 256 allows 1-byte codes (optimal)
- Higher K = better accuracy, larger codebook
Usage Examples
1. Create and Populate Index
-- Create tableCREATE TABLE embeddings ( id INTEGER PRIMARY KEY, text TEXT, vector VECTOR(384));
-- Create PQ indexCREATE INDEX emb_idx ON embeddings(vector)USING hnswWITH (quantization='product');
-- Insert vectors (automatically quantized)INSERT INTO embeddings (id, text, vector) VALUES(1, 'hello world', VECTOR([0.1, 0.2, ...])),(2, 'foo bar', VECTOR([0.3, 0.4, ...])),(3, 'test data', VECTOR([0.5, 0.6, ...]));2. Search with PQ Index
-- Vector similarity search (uses PQ automatically)SELECT id, text, vector_distance(vector, VECTOR([0.1, 0.2, ...])) as distanceFROM embeddingsORDER BY distanceLIMIT 10;3. Check Index Statistics
-- View index detailsSELECT index_name, num_vectors, dimensions, quantization, memory_bytes, memory_bytes / 1024.0 / 1024.0 as memory_mbFROM helios_vector_indexesWHERE quantization = 'Product';4. Compare Memory Usage
-- Create standard and PQ indexes for comparisonCREATE TABLE comparison ( id INTEGER PRIMARY KEY, vec VECTOR(768));
CREATE INDEX std_idx ON comparison(vec) USING hnsw;CREATE INDEX pq_idx ON comparison(vec) USING hnswWITH (quantization='product');
-- Insert test dataINSERT INTO comparison (id, vec)SELECT generate_series(1, 10000), random_vector(768);
-- Compare memory usageSELECT index_name, quantization, memory_bytes, memory_bytes / 1024.0 / 1024.0 as memory_mbFROM helios_vector_indexesWHERE table_name = 'comparison';Expected output:
index_name | quantization | memory_bytes | memory_mb-----------+--------------+--------------+----------std_idx | None | 30720000 | 29.30pq_idx | Product | 2048000 | 1.95Configuration Examples by Dimension
Common Embedding Dimensions
384 dimensions (MiniLM, etc.):
CREATE INDEX idx_384 ON table(vec) USING hnswWITH ( quantization='product', pq_subquantizers=4, -- 384/4 = 96 per subquantizer pq_centroids=256);768 dimensions (BERT, RoBERTa):
CREATE INDEX idx_768 ON table(vec) USING hnswWITH ( quantization='product', pq_subquantizers=8, -- 768/8 = 96 per subquantizer pq_centroids=256);1536 dimensions (OpenAI ada-002):
CREATE INDEX idx_1536 ON table(vec) USING hnswWITH ( quantization='product', pq_subquantizers=8, -- 1536/8 = 192 per subquantizer pq_centroids=256);Performance Characteristics
Memory Compression
| Dimension | Standard | PQ (M=8) | Compression |
|---|---|---|---|
| 128 | 512 B | 40 B | 12.8x |
| 384 | 1.5 KB | 40 B | 38.4x |
| 768 | 3.0 KB | 40 B | 76.8x |
| 1536 | 6.0 KB | 40 B | 153.6x |
Note: Actual compression includes codebook overhead
Search Accuracy
Typical recall@10 metrics:
- 95-98% with M=8, K=256
- 92-95% with M=4, K=256
- 88-92% with M=2, K=256
Query Performance
- PQ Search: ~5-10% slower than standard HNSW
- ADC Optimization: Precomputed distance tables minimize overhead
- Large Datasets: Performance gap decreases as dataset grows
Best Practices
1. Training Data
-- Let the index train on existing dataCREATE INDEX pq_idx ON large_table(vec) USING hnswWITH (quantization='product');
-- Index will use sample of existing vectors for training-- Minimum 10,000 vectors recommended for optimal training2. Dimension Selection
- Choose M such that D/M is between 64-128
- Common configurations:
- 384 dims: M=4 (96 per subquantizer)
- 768 dims: M=8 (96 per subquantizer)
- 1536 dims: M=12 or M=16
3. When to Use PQ
Use PQ when:
- Dataset > 100K vectors
- Memory is constrained
- High-dimensional vectors (>256 dims)
- Can tolerate 2-5% accuracy loss
Use standard HNSW when:
- Dataset < 10K vectors
- Maximum accuracy required
- Low-dimensional vectors (<128 dims)
- Memory is not constrained
Troubleshooting
Error: Dimension not divisible by subquantizers
-- This will fail: 100 is not divisible by 8CREATE INDEX bad_idx ON table(vec VECTOR(100)) USING hnswWITH (quantization='product', pq_subquantizers=8);
-- Solution: Use M=4 (100/4 = 25)CREATE INDEX good_idx ON table(vec VECTOR(100)) USING hnswWITH (quantization='product', pq_subquantizers=4);Insufficient Training Data
-- Error if table has < 10,000 vectorsCREATE INDEX pq_idx ON small_table(vec) USING hnswWITH (quantization='product');
-- Solution: Use standard index for small datasetsCREATE INDEX std_idx ON small_table(vec) USING hnsw;Low Search Accuracy
-- If recall is too low, increase MCREATE INDEX better_pq_idx ON table(vec VECTOR(768)) USING hnswWITH ( quantization='product', pq_subquantizers=16 -- Increased from 8);Migration Guide
Migrating Existing Indexes to PQ
-- 1. Create new PQ indexCREATE INDEX new_pq_idx ON documents(embedding) USING hnswWITH (quantization='product');
-- 2. Test search qualitySELECT id FROM documentsUSE INDEX (new_pq_idx)ORDER BY vector_distance(embedding, VECTOR(?))LIMIT 10;
-- 3. Drop old index if satisfiedDROP INDEX old_idx;Monitoring
Index Health
SELECT index_name, num_vectors, quantization, memory_bytes, memory_bytes::float / num_vectors as bytes_per_vector, recall_at_10FROM helios_vector_indexesWHERE quantization = 'Product';Performance Metrics
-- Track query performanceEXPLAIN ANALYZESELECT id FROM documentsORDER BY vector_distance(embedding, VECTOR(?))LIMIT 10;Advanced Topics
Custom Distance Metrics
-- PQ supports different distance metricsCREATE INDEX cosine_pq_idx ON documents(embedding) USING hnswWITH ( quantization='product', distance_metric='cosine');Hybrid Indexes
-- Use PQ for large-scale search, standard for refinementCREATE INDEX pq_idx ON documents(embedding) USING hnswWITH (quantization='product');
CREATE INDEX std_idx ON top_results(embedding) USING hnsw;
-- Two-stage searchWITH candidates AS ( SELECT id FROM documents USE INDEX (pq_idx) ORDER BY vector_distance(embedding, VECTOR(?)) LIMIT 100)SELECT id FROM candidatesJOIN documents USING (id)USE INDEX (std_idx)ORDER BY vector_distance(embedding, VECTOR(?))LIMIT 10;