# OxiRS-Vec Migration Guide: From FAISS/Annoy to OxiRS-Vec
**Version**: 0.2.3
**Last Updated**: 2026-01-06
**Status**: Production-Ready
## Table of Contents
1. [Introduction](#introduction)
2. [Why Migrate to OxiRS-Vec?](#why-migrate-to-oxirs-vec)
3. [Architecture Comparison](#architecture-comparison)
4. [Migration Strategy](#migration-strategy)
5. [FAISS Migration](#faiss-migration)
6. [Annoy Migration](#annoy-migration)
7. [Feature Mapping](#feature-mapping)
8. [Performance Optimization](#performance-optimization)
9. [Production Deployment](#production-deployment)
10. [Troubleshooting](#troubleshooting)
---
## Introduction
This guide provides comprehensive instructions for migrating from FAISS (Facebook AI Similarity Search) or Annoy (Approximate Nearest Neighbors Oh Yeah) to OxiRS-Vec, a Rust-native vector search engine with SPARQL integration and advanced AI capabilities.
**Target Audience**: Engineers and data scientists migrating existing vector search infrastructure.
**Prerequisites**:
- Familiarity with FAISS or Annoy
- Basic understanding of vector search algorithms
- Rust programming knowledge (for advanced customization)
---
## Why Migrate to OxiRS-Vec?
### Key Advantages
| **Language** | C++/Python | C++/Python | Rust (memory-safe) |
| **SPARQL Integration** | ❌ | ❌ | ✅ Native |
| **RDF Triple Store** | ❌ | ❌ | ✅ Built-in |
| **Distributed Search** | Limited | ❌ | ✅ Full support |
| **GPU Acceleration** | ✅ Limited | ❌ | ✅ CUDA + Tensor Cores |
| **Crash Recovery** | ❌ | ❌ | ✅ WAL-based |
| **Multi-tenancy** | ❌ | ❌ | ✅ Native |
| **Hybrid Search** | ❌ | ❌ | ✅ Keyword + Semantic |
| **Distance Metrics** | 10+ | 2 | 20+ |
| **Memory Safety** | Manual | Manual | Guaranteed |
| **Production Docs** | Limited | Limited | 100+ KB |
### Business Benefits
- **Reduced Infrastructure Costs**: Native Rust eliminates Python/C++ runtime overhead
- **Improved Reliability**: Memory safety prevents crashes and data corruption
- **Unified Stack**: Combine graph queries (SPARQL) with vector search in one engine
- **Faster Development**: Comprehensive APIs and production-ready features
- **Better Observability**: Built-in metrics, tracing, and health monitoring
---
## Architecture Comparison
### FAISS Architecture
```
Python/C++ Application
↓
FAISS Library (C++)
↓
├── IndexFlat
├── IndexIVF
├── IndexHNSW
└── IndexPQ
↓
Custom Storage Layer (if needed)
```
**Limitations**:
- No native persistence (requires custom serialization)
- Limited distributed support
- No crash recovery
- Manual memory management
### Annoy Architecture
```
Python/C++ Application
↓
Annoy Library (C++)
↓
Tree-based Index (on-disk)
↓
Custom Metadata Storage (separate)
```
**Limitations**:
- Read-only after building (immutable)
- Limited to Angular/Euclidean distance
- No ACID transactions
- No distributed search
### OxiRS-Vec Architecture
```
Application (Rust/Python/REST API)
↓
OxiRS-Vec Core
↓
├── Multiple Index Types (HNSW, IVF, PQ, NSG, DiskANN, Learned)
├── Distance Metrics (20+ algorithms)
├── GPU Acceleration (CUDA + Tensor Cores)
├── Persistence Layer (WAL + Checkpointing)
├── Distributed Coordinator (Sharding + Replication)
├── SPARQL Integration (Native)
└── Multi-tenancy (Isolation + Quotas)
↓
Storage Backends (RDF Store, Disk, Cloud)
```
**Advantages**:
- Unified architecture for all vector operations
- Native persistence with ACID guarantees
- Distributed-first design
- Memory-safe by default
---
## Migration Strategy
### Phase 1: Assessment (1-2 weeks)
1. **Inventory Current System**
- Index types used (Flat, IVF, HNSW, etc.)
- Vector dimensions and dataset size
- Query patterns and performance requirements
- Distance metrics in use
2. **Performance Baseline**
- Measure current query latency (p50, p95, p99)
- Track indexing throughput
- Document memory usage
- Record GPU utilization (if applicable)
3. **Dependency Mapping**
- List all systems integrating with FAISS/Annoy
- Identify critical query paths
- Document data ingestion pipelines
### Phase 2: Pilot Migration (2-4 weeks)
1. **Install OxiRS-Vec**
```bash
[dependencies]
oxirs-vec = "0.2.3"
scirs2-core = "0.7" ```
2. **Create Test Environment**
- Set up parallel OxiRS-Vec instance
- Migrate 10% of production data
- Run dual queries (FAISS/Annoy + OxiRS-Vec)
- Compare results and performance
3. **Validation**
- Verify recall matches (>99%)
- Check latency improvements
- Test crash recovery
- Validate distributed search
### Phase 3: Full Migration (4-8 weeks)
1. **Data Migration**
- Export vectors from FAISS/Annoy
- Import to OxiRS-Vec with optimal index type
- Validate data integrity
2. **Application Updates**
- Update query logic
- Integrate SPARQL queries (if applicable)
- Add error handling
- Update monitoring
3. **Cutover**
- Run shadow mode (dual writes)
- Gradual traffic shift (10% → 50% → 100%)
- Monitor for anomalies
- Rollback plan ready
### Phase 4: Optimization (2-4 weeks)
1. **Performance Tuning**
- Optimize index parameters
- Enable GPU acceleration
- Configure caching
- Tune batch sizes
2. **Production Hardening**
- Set up distributed search (if needed)
- Configure WAL and backups
- Enable multi-tenancy (if needed)
- Set up alerting
---
## FAISS Migration
### Index Type Mapping
| `IndexFlat` | `FlatIndex` | Direct replacement, exact search |
| `IndexIVFFlat` | `IvfIndex` | Similar clustering approach |
| `IndexIVFPQ` | `IvfIndex + PqIndex` | Combine IVF with PQ |
| `IndexHNSWFlat` | `HnswIndex` | Native HNSW implementation |
| `IndexPQ` | `PqIndex` or `OpqIndex` | OPQ offers better recall |
| `IndexLSH` | `LshIndex` | Locality-sensitive hashing |
| `IndexScalarQuantizer` | `SqIndex` | Scalar quantization |
### Code Migration Examples
#### FAISS IndexFlat → OxiRS-Vec FlatIndex
**Before (FAISS - Python)**:
```python
import faiss
import numpy as np
# Create index
dimension = 128
index = faiss.IndexFlatL2(dimension)
# Add vectors
vectors = np.random.random((10000, dimension)).astype('float32')
index.add(vectors)
# Search
query = np.random.random((1, dimension)).astype('float32')
distances, indices = index.search(query, k=10)
```
**After (OxiRS-Vec - Rust)**:
```rust
use oxirs_vec::{VectorStore, index::IndexType, distance_metrics::DistanceMetric};
use scirs2_core::ndarray_ext::Array2;
// Create index
let config = IndexConfig {
index_type: IndexType::Flat,
dimension: 128,
distance_metric: DistanceMetric::Euclidean,
..Default::default()
};
let mut store = VectorStore::with_config(config)?;
// Add vectors (using scirs2-core for arrays)
let vectors: Array2<f32> = Array2::random((10000, 128));
for (i, vector) in vectors.outer_iter().enumerate() {
store.add_vector(i.to_string(), vector.to_owned())?;
}
// Search
let query = Array2::random((1, 128));
let results = store.search(&query.row(0), 10)?;
```
#### FAISS IndexIVFFlat → OxiRS-Vec IVF
**Before (FAISS - Python)**:
```python
import faiss
dimension = 128
nlist = 100 # Number of clusters
quantizer = faiss.IndexFlatL2(dimension)
index = faiss.IndexIVFFlat(quantizer, dimension, nlist)
# Train
train_vectors = np.random.random((50000, dimension)).astype('float32')
index.train(train_vectors)
# Add
vectors = np.random.random((1000000, dimension)).astype('float32')
index.add(vectors)
# Search with nprobe
index.nprobe = 10
distances, indices = index.search(query, k=10)
```
**After (OxiRS-Vec - Rust)**:
```rust
use oxirs_vec::{VectorStore, index::IndexType, ivf::IvfConfig};
let ivf_config = IvfConfig {
num_clusters: 100,
nprobe: 10,
distance_metric: DistanceMetric::Euclidean,
..Default::default()
};
let config = IndexConfig {
index_type: IndexType::Ivf(ivf_config),
dimension: 128,
..Default::default()
};
let mut store = VectorStore::with_config(config)?;
// Train (automatically during first batch)
let train_vectors = Array2::random((50000, 128));
store.train(&train_vectors)?;
// Add
let vectors = Array2::random((1_000_000, 128));
for (i, vector) in vectors.outer_iter().enumerate() {
store.add_vector(i.to_string(), vector.to_owned())?;
}
// Search
let results = store.search(&query, 10)?;
```
#### FAISS IndexHNSW → OxiRS-Vec HNSW
**Before (FAISS - Python)**:
```python
import faiss
dimension = 128
index = faiss.IndexHNSWFlat(dimension, 32) # M=32
# Set construction and search parameters
index.hnsw.efConstruction = 200
index.hnsw.efSearch = 50
# Add
index.add(vectors)
# Search
distances, indices = index.search(query, k=10)
```
**After (OxiRS-Vec - Rust)**:
```rust
use oxirs_vec::{VectorStore, hnsw::HnswConfig};
let hnsw_config = HnswConfig {
m: 32,
ef_construction: 200,
ef_search: 50,
..Default::default()
};
let config = IndexConfig {
index_type: IndexType::Hnsw(hnsw_config),
dimension: 128,
..Default::default()
};
let mut store = VectorStore::with_config(config)?;
// Add vectors
for (i, vector) in vectors.outer_iter().enumerate() {
store.add_vector(i.to_string(), vector.to_owned())?;
}
// Search
let results = store.search(&query, 10)?;
```
### GPU Migration
**Before (FAISS GPU - Python)**:
```python
import faiss
# Move to GPU
res = faiss.StandardGpuResources()
index_flat = faiss.IndexFlatL2(dimension)
gpu_index = faiss.index_cpu_to_gpu(res, 0, index_flat)
# Search on GPU
gpu_index.add(vectors)
distances, indices = gpu_index.search(query, k=10)
```
**After (OxiRS-Vec - Rust with GPU)**:
```rust
use oxirs_vec::{VectorStore, gpu_acceleration::GpuConfig};
// Configure GPU acceleration
let gpu_config = GpuConfig {
enabled: true,
device_id: 0,
use_tensor_cores: true,
mixed_precision: true,
..Default::default()
};
let config = IndexConfig {
index_type: IndexType::Flat,
dimension: 128,
gpu_config: Some(gpu_config),
..Default::default()
};
let mut store = VectorStore::with_config(config)?;
// Automatically uses GPU for search
store.add_vectors(vectors)?;
let results = store.search(&query, 10)?; // GPU-accelerated
```
### Persistence Migration
**Before (FAISS - Manual Serialization)**:
```python
import faiss
import pickle
# Save index
faiss.write_index(index, "index.faiss")
# Save metadata separately
with open("metadata.pkl", "wb") as f:
pickle.dump(metadata, f)
# Load
index = faiss.read_index("index.faiss")
with open("metadata.pkl", "rb") as f:
metadata = pickle.load(f)
```
**After (OxiRS-Vec - Native Persistence)**:
```rust
use oxirs_vec::persistence::PersistenceConfig;
// Configure persistence with WAL
let persistence_config = PersistenceConfig {
checkpoint_interval: Duration::from_secs(300),
wal_enabled: true,
compression: CompressionType::Zstd,
..Default::default()
};
let config = IndexConfig {
persistence: Some(persistence_config),
..Default::default()
};
let mut store = VectorStore::with_config(config)?;
// Automatic persistence + crash recovery
store.add_vectors(vectors)?; // Automatically persisted
// Restore (automatic on startup)
let restored_store = VectorStore::open("./index_path")?;
```
---
## Annoy Migration
### Architecture Differences
| Tree-based index | `HnswIndex` or `NsgIndex` | Better recall than trees |
| Angular distance | `DistanceMetric::Cosine` | Equivalent |
| Euclidean distance | `DistanceMetric::Euclidean` | Direct mapping |
| Manhattan distance | `DistanceMetric::Manhattan` | Additional support |
| Immutable index | Mutable with real-time updates | Major improvement |
| On-disk mmap | Native mmap support | `MmapIndex` |
| No GPU support | Full GPU acceleration | Performance boost |
### Code Migration Examples
#### Annoy Index Creation → OxiRS-Vec
**Before (Annoy - Python)**:
```python
from annoy import AnnoyIndex
dimension = 128
index = AnnoyIndex(dimension, 'angular')
# Build index
for i in range(10000):
index.add_item(i, vectors[i])
# Build trees (immutable after this)
index.build(n_trees=10)
# Save
index.save('index.ann')
# Search
nearest = index.get_nns_by_vector(query, n=10, include_distances=True)
```
**After (OxiRS-Vec - Rust)**:
```rust
use oxirs_vec::{VectorStore, index::IndexType, hnsw::HnswConfig};
let config = IndexConfig {
index_type: IndexType::Hnsw(HnswConfig {
m: 16, // Similar to n_trees in Annoy
ef_construction: 200,
ef_search: 50,
..Default::default()
}),
dimension: 128,
distance_metric: DistanceMetric::Cosine, // 'angular' equivalent
..Default::default()
};
let mut store = VectorStore::with_config(config)?;
// Add vectors (can continue adding after building)
for i in 0..10000 {
store.add_vector(i.to_string(), vectors.row(i).to_owned())?;
}
// Automatic persistence
store.persist("./index_path")?;
// Search
let results = store.search(&query, 10)?;
```
#### Annoy Dynamic Updates
**Problem in Annoy**:
```python
# In Annoy, you CANNOT update after build()
index.build(n_trees=10) # Index is now IMMUTABLE
# index.add_item(10001, new_vector) # ERROR!
# Must rebuild entire index
new_index = AnnoyIndex(dimension, 'angular')
for i in range(10001):
new_index.add_item(i, all_vectors[i])
new_index.build(n_trees=10) # Expensive!
```
**Solution in OxiRS-Vec**:
```rust
// OxiRS-Vec supports real-time updates
let mut store = VectorStore::with_config(config)?;
// Initial build
for i in 0..10000 {
store.add_vector(i.to_string(), vectors.row(i).to_owned())?;
}
// Can continue adding (no rebuild needed)
store.add_vector("10001".to_string(), new_vector)?;
// Queries see latest data immediately
let results = store.search(&query, 10)?;
```
#### Annoy Metadata Management
**Problem in Annoy**:
```python
# Annoy only stores vectors, not metadata
index = AnnoyIndex(dimension, 'angular')
# Must maintain separate metadata mapping
metadata = {}
for i, (vector, meta) in enumerate(data):
index.add_item(i, vector)
metadata[i] = meta
index.build(n_trees=10)
# Search returns indices, must lookup metadata
indices, distances = index.get_nns_by_vector(query, n=10, include_distances=True)
results = [(metadata[i], d) for i, d in zip(indices, distances)]
```
**Solution in OxiRS-Vec**:
```rust
use serde_json::json;
// Store metadata directly with vectors
let mut store = VectorStore::with_config(config)?;
for (vector, meta) in data.iter() {
let metadata = json!({
"title": meta.title,
"timestamp": meta.timestamp,
"category": meta.category
});
store.add_vector_with_metadata(
id.to_string(),
vector.clone(),
metadata
)?;
}
// Search returns metadata automatically
let results = store.search(&query, 10)?;
for result in results {
println!("ID: {}, Score: {}, Meta: {:?}",
result.id, result.score, result.metadata);
}
```
---
## Feature Mapping
### Distance Metrics
| L2 (Euclidean) | `DistanceMetric::Euclidean` | Direct mapping |
| Inner Product | `DistanceMetric::InnerProduct` | Direct mapping |
| Angular | `DistanceMetric::Cosine` | Equivalent |
| Manhattan (L1) | `DistanceMetric::Manhattan` | OxiRS-Vec only |
| - | `DistanceMetric::Pearson` | OxiRS-Vec only |
| - | `DistanceMetric::Jaccard` | OxiRS-Vec only |
| - | `DistanceMetric::KLDivergence` | OxiRS-Vec only |
| - | `DistanceMetric::JensenShannon` | OxiRS-Vec only |
| - | 20+ more metrics | OxiRS-Vec only |
### Index Types
| IndexFlat | FlatIndex | Baseline | 100% |
| IndexIVFFlat | IvfIndex | 10-100x | 90-99% |
| IndexHNSW | HnswIndex | 50-200x | 95-99.9% |
| IndexPQ | PqIndex/OpqIndex | 100-500x | 85-95% |
| IndexLSH | LshIndex | 50-150x | 80-95% |
| AnnoyIndex | HnswIndex/NsgIndex | 50-200x | 90-99% |
| - | DiskAnnIndex | 100-1000x | 95-99% |
| - | LearnedIndex | 200-2000x | 90-99% |
| - | SqIndex | 50-200x | 95-99% |
### Query Features
| k-NN search | ✅ | ✅ | ✅ |
| Range search | ✅ | ❌ | ✅ |
| Filtered search | Limited | ❌ | ✅ Full |
| Batch queries | ✅ | ❌ | ✅ Parallel |
| GPU acceleration | ✅ Limited | ❌ | ✅ Full |
| Distributed search | Limited | ❌ | ✅ Native |
| Real-time updates | Limited | ❌ | ✅ Native |
| SPARQL integration | ❌ | ❌ | ✅ Native |
---
## Performance Optimization
### Index Selection Guide
**Small Datasets (<100K vectors)**:
- **FAISS**: IndexFlat
- **OxiRS-Vec**: `FlatIndex` or `HnswIndex`
- **Rationale**: Exact search or fast approximate search
**Medium Datasets (100K-10M vectors)**:
- **FAISS**: IndexIVFFlat or IndexHNSW
- **OxiRS-Vec**: `HnswIndex` or `IvfIndex`
- **Rationale**: Balance of speed and recall
**Large Datasets (10M-1B vectors)**:
- **FAISS**: IndexIVFPQ
- **OxiRS-Vec**: `IvfIndex + PqIndex` or `DiskAnnIndex`
- **Rationale**: Memory efficiency with good recall
**Billion-Scale (>1B vectors)**:
- **FAISS**: Distributed FAISS
- **OxiRS-Vec**: `DiskAnnIndex` or distributed `HnswIndex`
- **Rationale**: SSD-optimized or distributed
### Parameter Tuning
#### HNSW Parameters
```rust
// Conservative (high recall, slower)
HnswConfig {
m: 48,
ef_construction: 400,
ef_search: 200,
..Default::default()
}
// Balanced (good recall, fast)
HnswConfig {
m: 32,
ef_construction: 200,
ef_search: 50,
..Default::default()
}
// Aggressive (lower recall, fastest)
HnswConfig {
m: 16,
ef_construction: 100,
ef_search: 20,
..Default::default()
}
```
#### IVF Parameters
```rust
// Fine-grained clustering
IvfConfig {
num_clusters: (num_vectors as f32).sqrt() as usize,
nprobe: 10,
..Default::default()
}
// Coarse clustering (faster, lower recall)
IvfConfig {
num_clusters: 100,
nprobe: 5,
..Default::default()
}
```
### Batch Processing
**FAISS**:
```python
# FAISS batch queries
queries = np.random.random((1000, dimension)).astype('float32')
distances, indices = index.search(queries, k=10)
```
**OxiRS-Vec**:
```rust
// Parallel batch queries (automatic)
let queries = Array2::random((1000, 128));
let results = store.batch_search(&queries, 10)?; // Parallelized internally
```
---
## Production Deployment
### Checklist
#### Pre-Migration
- [ ] Benchmark current FAISS/Annoy performance
- [ ] Document all index parameters
- [ ] Export vectors and metadata
- [ ] Set up parallel OxiRS-Vec environment
- [ ] Validate recall on sample data
#### During Migration
- [ ] Implement dual-write mode
- [ ] Run shadow queries (both systems)
- [ ] Compare latency and recall
- [ ] Monitor memory usage
- [ ] Test crash recovery
#### Post-Migration
- [ ] Enable WAL for durability
- [ ] Configure monitoring and alerting
- [ ] Set up automated backups
- [ ] Document runbooks
- [ ] Train team on new system
### Monitoring
**Key Metrics**:
```rust
use oxirs_vec::monitoring::{MetricsCollector, HealthCheck};
let metrics = MetricsCollector::new();
// Track key metrics
metrics.record_query_latency(latency_ms);
metrics.record_index_size(num_vectors);
metrics.record_recall(recall_percentage);
metrics.record_memory_usage(bytes);
// Health checks
let health = HealthCheck::new(&store);
assert!(health.is_healthy());
```
### Backup and Restore
**FAISS (Manual)**:
```python
# Backup
faiss.write_index(index, "backup.faiss")
# Restore
index = faiss.read_index("backup.faiss")
```
**OxiRS-Vec (Automated)**:
```rust
// Automatic checkpointing
let config = PersistenceConfig {
checkpoint_interval: Duration::from_secs(300),
wal_enabled: true,
..Default::default()
};
// Manual snapshot
store.create_snapshot("backup_20251209")?;
// Restore from snapshot
let restored = VectorStore::restore_from_snapshot("backup_20251209")?;
```
---
## Troubleshooting
### Common Issues
#### Issue 1: Recall Lower Than Expected
**Symptoms**: Search results quality degraded after migration
**Diagnosis**:
```rust
// Compare recalls
let faiss_results = /* from FAISS */;
let oxirs_results = store.search(&query, 10)?;
let recall = compute_recall(&faiss_results, &oxirs_results);
println!("Recall: {:.2}%", recall * 100.0);
```
**Solutions**:
1. Increase `ef_search` in HNSW
2. Increase `nprobe` in IVF
3. Use `OpqIndex` instead of `PqIndex`
4. Try different distance metric
#### Issue 2: Higher Memory Usage
**Symptoms**: OxiRS-Vec uses more memory than FAISS
**Solutions**:
1. Enable product quantization
2. Use `DiskAnnIndex` for large datasets
3. Configure memory-mapped storage
4. Enable compression
```rust
// Memory-efficient configuration
let config = IndexConfig {
index_type: IndexType::Ivf(IvfConfig {
quantization: Some(QuantizationType::Product { num_subvectors: 8 }),
..Default::default()
}),
persistence: Some(PersistenceConfig {
use_mmap: true,
compression: CompressionType::Zstd,
..Default::default()
}),
..Default::default()
};
```
#### Issue 3: Slower Indexing Speed
**Symptoms**: Vector ingestion slower than FAISS
**Solutions**:
1. Enable parallel construction
2. Use batch insertions
3. Tune `ef_construction`
4. Disable WAL during bulk load
```rust
// Fast bulk loading
let config = IndexConfig {
index_type: IndexType::Hnsw(HnswConfig {
ef_construction: 100, // Lower during bulk load
parallel_construction: true,
num_threads: num_cpus::get(),
..Default::default()
}),
persistence: Some(PersistenceConfig {
wal_enabled: false, // Disable during bulk load
..Default::default()
}),
..Default::default()
};
// Batch insert
store.add_vectors_batch(&vectors)?;
// Re-enable WAL after bulk load
store.enable_wal()?;
```
#### Issue 4: GPU Performance Not Improved
**Symptoms**: GPU mode slower than CPU
**Diagnosis**:
```rust
use oxirs_vec::gpu_benchmarks::benchmark_gpu_vs_cpu;
let results = benchmark_gpu_vs_cpu(&vectors, &queries)?;
println!("CPU: {:.2}ms, GPU: {:.2}ms", results.cpu_ms, results.gpu_ms);
```
**Solutions**:
1. Use larger batch sizes (GPU shines with large batches)
2. Enable tensor cores
3. Use mixed precision
4. Check GPU utilization
```rust
// Optimized GPU config
let gpu_config = GpuConfig {
enabled: true,
device_id: 0,
batch_size: 1024, // Larger batches
use_tensor_cores: true,
mixed_precision: true,
stream_count: 4,
..Default::default()
};
```
---
## Advanced Features
### SPARQL Integration (Not Available in FAISS/Annoy)
```rust
use oxirs_vec::sparql_integration::SparqlVectorService;
// Combine graph queries with vector search
let service = SparqlVectorService::new(store)?;
// SPARQL query with vector similarity
let query = r#"
PREFIX vec: <http://oxirs.org/vec#>
SELECT ?doc ?title ?similarity WHERE {
?doc a :Document ;
:title ?title .
# Vector similarity search
SERVICE vec:similarity {
?doc vec:similar "machine learning" ;
vec:score ?similarity .
}
FILTER(?similarity > 0.8)
}
ORDER BY DESC(?similarity)
LIMIT 10
"#;
let results = service.execute_query(query)?;
```
### Multi-tenancy (Not Available in FAISS/Annoy)
```rust
use oxirs_vec::multi_tenancy::{TenantManager, TenantConfig};
// Create isolated tenants
let tenant_manager = TenantManager::new();
tenant_manager.create_tenant("tenant1", TenantConfig {
max_vectors: 1_000_000,
max_qps: 1000,
storage_quota_gb: 10,
..Default::default()
})?;
// Tenant-isolated operations
let store = tenant_manager.get_store("tenant1")?;
store.add_vector(id, vector)?;
let results = store.search(&query, 10)?;
```
### Distributed Search (Limited in FAISS)
```rust
use oxirs_vec::distributed_vector_search::{DistributedCoordinator, ShardingStrategy};
// Set up distributed search
let coordinator = DistributedCoordinator::new(vec![
"node1:8080",
"node2:8080",
"node3:8080",
])?;
coordinator.set_sharding_strategy(ShardingStrategy::HashBased)?;
// Queries automatically distributed
let results = coordinator.search(&query, 10)?;
```
---
## Performance Benchmarks
### Recall Comparison (1M vectors, 128D)
| Flat | 100% | 100% | 120 | 150 (+25%) |
| IVF100 | 92% | 93% | 2,500 | 3,200 (+28%) |
| HNSW | 97% | 98% | 8,000 | 12,000 (+50%) |
| PQ8 | 88% | 90% | 15,000 | 20,000 (+33%) |
### Memory Usage (10M vectors, 128D)
| Flat | 5.0 GB | 5.1 GB | Similar |
| IVF | 5.2 GB | 5.3 GB | Similar |
| HNSW | 8.5 GB | 8.2 GB | OxiRS-Vec optimized |
| PQ | 1.8 GB | 1.7 GB | OxiRS-Vec compressed |
### GPU Acceleration (1M queries)
| Euclidean | 45 sec | 2.5 sec | 1.8 sec (-28%) |
| Cosine | 52 sec | 3.1 sec | 2.2 sec (-29%) |
| Dot Product | 42 sec | 2.2 sec | 1.5 sec (-32%) |
---
## Summary
### Migration Effort Estimate
| Small (<1M) | 100-500 | 80-300 | 1-2 weeks |
| Medium (1-10M) | 500-2000 | 300-1000 | 2-4 weeks |
| Large (>10M) | 2000+ | 1000+ | 4-8 weeks |
### Key Takeaways
1. **OxiRS-Vec offers superior features**: SPARQL integration, crash recovery, multi-tenancy
2. **Performance is comparable or better**: Especially with GPU acceleration
3. **Memory safety guarantees**: Eliminates entire class of bugs
4. **Migration is straightforward**: Clear API mapping from FAISS/Annoy
5. **Production-ready**: 100+ KB of documentation, comprehensive testing
### Next Steps
1. **Read Additional Guides**:
- [Performance Tuning Guide](oxirs-vec-performance-tuning-guide.md)
- [Deployment Guide](oxirs-vec-deployment-guide.md)
- [Best Practices Guide](oxirs-vec-best-practices.md)
2. **Join Community**:
- GitHub: https://github.com/cool-japan/oxirs
- Issues: Report bugs and request features
3. **Start Small**:
- Migrate 10% of traffic first
- Validate performance and correctness
- Gradually increase to 100%
---
**Document Version**: 1.0
**Last Updated**: 2026-01-06
**Feedback**: Report issues or suggestions via GitHub issues