向量检索是语义搜索和RAG系统的核心能力,ScaNN、Faiss和Milvus是三大主流引擎。本文从检索精度、吞吐性能、分布式支持和易用性等维度对比三者的特点,帮助开发者根据场景选择合适的向量检索方案。适合搭建向量搜索和RAG应用的工程师。
需要学习ScaNN/Faiss/Milvus引擎对比,这是你的核心专业课,从倒排索引到向量检索,推荐系统的全链路技术。本篇涵盖召回/排序/重排、向量检索、语义搜索,帮助你构建搜索推荐系统。
可视化演示
通过多维度雷达对比、最近邻检索动画和索引结构图,直观展示ScaNN、Faiss、Milvus三大引擎的核心差异与选型策略。
本节配有交互动效(进入视口后自动加载,约 3KB)。
三引擎多维雷达对比 ScaNN:精度最优,各向异性量化 Faiss:索引最丰富,GPU加速 Recall@k = |ANN ∩ GT| / k Milvus:分布式架构,全功能向量数据库
三大引擎定位与核心差异
在大规模向量检索领域,ScaNN、Faiss和Milvus是三大主流引擎,它们分别面向不同的应用场景和部署模式。ScaNN由Google Research开发,核心创新在于各向异性向量量化(Anisotropic Vector Quantization, AVQ),专注于单机环境下的高精度近似最近邻搜索。Faiss由Meta AI开源,提供了最丰富的索引类型组合(IVF、HNSW、PQ及其变体),并支持GPU加速大规模批量检索。Milvus则是一个完整的分布式云原生向量数据库,提供存算分离架构、动态数据更新和高可用保障。
定位对比: | 维度 | ScaNN | Faiss | Milvus | |------|-------|-------|--------| | 开发者 | Google Research | Meta AI | Zilliz/LF AI | | 定位 | 高精度单机检索库 | 通用向量检索库 | 分布式向量数据库 | | 分布式 | 不支持 | 不支持(需自建) | 原生支持 | | GPU加速 | 不支持 | 支持 | 支持 | | 动态更新 | 不支持 | 有限支持 | 完整CRUD | | 适用规模 | 百万级 | 亿级(单机) | 十亿级+ | 可以用一个类比来理解:ScaNN是跑车(精度最高但载量小),Faiss是卡车(灵活载货),Milvus是物流车队(分布式运营)。
ScaNN各向异性量化技术
ScaNN的核心创新是各向异性向量量化(Anisotropic Vector Quantization, AVQ)。传统的乘积量化(PQ)采用各向同性策略,将向量空间均匀划分为子空间并独立量化每个子空间。这种方法最小化了整体的均方误差,但对于内积检索任务来说并非最优。
AVQ的核心思想: 内积检索的目标是最大化查询向量与文档向量的内积,而非最小化量化误差。AVQ通过以下方式优化: 1. 在量化时考虑查询向量的方向分布 2. 允许量化误差在平行于查询向量的方向上更大,在垂直方向上更小 3. 这种各向异性的误差分配使得内积估计的偏差更小 数学直觉: 设原始向量为 v,量化向量为 Q(v),内积误差为 <q, v> - <q, Q(v)> = <q, v - Q(v)>。AVQ通过使量化误差 v - Q(v) 与查询向量 q 的方向尽量正交,来减小内积误差。 局限性: ScaNN不支持分布式部署,数据规模受限于单机内存。适合百万级向量的高精度检索场景。
Faiss索引类型与GPU加速
Faiss(Facebook AI Similarity Search)由Meta AI开源,是目前使用最广泛的向量检索库。它提供了最丰富的索引类型组合,可以根据数据规模和延迟要求进行灵活选择。
核心索引类型: 1. Flat(暴力搜索):100%召回率,O(n)复杂度,适合小规模数据或baseline 2. IVF(倒排文件索引):将向量空间划分为nlist个Voronoi单元,查询时只搜索最近的nprobe个单元。复杂度O(n·nprobe/nlist) 3. HNSW(分层导航小世界图):基于图的索引,O(log n)查询复杂度,内存占用较高 4. PQ(乘积量化):将高维向量分割为多个子空间并独立量化,大幅压缩内存 5. OPQ(优化乘积量化):在PQ之前加一个旋转矩阵,使子空间之间的方差更均匀 组合索引: Faiss支持将多种索引组合使用,如 IVF-PQ(先IVF粗筛再PQ精排)、IVF-HNSW(IVF粗筛+HNSW精搜)。最常用的生产配置是 IVF-HNSW-PQ。 GPU加速: Faiss的GPU实现基于CUDA,支持批量查询的并行加速。在大规模批量检索场景下(如离线处理),GPU可以将吞吐量提升10-100倍。但GPU加速主要适用于Flat和IVF类索引,HNSW的GPU支持有限。
Milvus分布式架构设计
Milvus是一个完整的分布式云原生向量数据库,与ScaNN和Faiss(都是检索库)不同,Milvus提供了完整的数据管理能力,包括CRUD操作、事务、权限控制和监控。
存算分离架构: Milvus采用存算分离的三层架构: 1. 接入层(Coordinator):负责元数据管理、调度和负载均衡 2. 计算层(Worker Nodes):包括数据节点(Data Node)、查询节点(Query Node)、索引节点(Index Node) 3. 存储层(Storage):基于对象存储(如S3/MinIO),数据持久化到远程存储 这种架构使得计算和存储可以独立扩缩容。当查询负载增加时,只需增加Query Node;当数据量增加时,只需增加Data Node和存储空间。 动态数据更新: 与Faiss不同,Milvus完整支持数据的增删改操作: - Insert:新向量实时可查(近实时,取决于refresh间隔) - Delete:通过标记删除实现,后台异步清理 - Update:先删除旧向量再插入新向量 高可用保障: - 数据多副本:每个segment有多个副本分布在不同节点 - 查询节点无状态:可水平扩展,故障自动恢复 - WAL(Write-Ahead Log):保证数据不丢失 类比:如果Faiss只管找书,Milvus还管入库、借阅、盘点,是一个完整的图书管理系统。
引擎选型与基准测试
选择合适的向量检索引擎需要综合考虑数据规模、延迟要求、吞吐需求、运维成本等多个维度。没有绝对最优的引擎,只有最适合业务场景的选择。
选型决策树: 1. 数据规模 < 百万级,追求最高精度 → ScaNN - 优势:AVQ量化精度最高,单机recall最优 - 限制:不支持分布式,无GPU加速 2. 数据规模 百万~亿级,需要GPU加速 → Faiss - 优势:索引类型丰富,GPU批量加速,社区活跃 - 限制:需自行管理数据持久化和分布式 3. 数据规模 亿级以上,需要分布式和高可用 → Milvus - 优势:原生分布式,完整数据管理,云原生 - 限制:运维复杂度较高,资源开销大 基准测试维度: | 指标 | 说明 | 建议阈值 | |------|------|----------| | Recall@10 | top-10结果中相关文档的比例 | > 95% | | P99延迟 | 99%查询的响应时间 | < 50ms | | QPS | 每秒查询数 | 根据业务需求 | | 内存占用 | 索引占用的内存 | 根据预算 | | 构建时间 | 索引构建耗时 | 根据更新频率 | 实际案例: 某RAG问答系统需要检索亿级文档向量。对比三引擎后选择Milvus,因为需要分布式部署和动态数据更新,亿级向量检索延迟8ms。Faiss单机GPU加速适合实验验证,ScaNN精度最高但无法分布式。
AI 应用场景
大规模推荐系统向量召回
RAG检索增强生成系统
多模态搜索引擎
Python 演示
import numpy as npimport timefrom typing import List, Tuple def benchmark_flat(vecs: np.ndarray, queries: np.ndarray, k: int = 10) -> Tuple[List[int], float]: """暴力搜索baseline(等价于Faiss IndexFlatIP)""" norms_v = vecs / (np.linalg.norm(vecs, axis=1, keepdims=True) + 1e-8) norms_q = queries / (np.linalg.norm(queries, axis=1, keepdims=True) + 1e-8) start = time.time() scores = norms_q @ norms_v.T indices = np.argsort(-scores, axis=1)[:, :k] elapsed = time.time() - start return indices.tolist(), elapsed def benchmark_ivf(vecs: np.ndarray, queries: np.ndarray, k: int = 10, nlist: int = 100, nprobe: int = 10) -> Tuple[List[int], float]: """IVF索引模拟(等价于Faiss IndexIVFFlat)""" from sklearn.cluster import KMeans dim = vecs.shape[1] kmeans = KMeans(n_clusters=nlist, random_state=42).fit(vecs) centroids = kmeans.cluster_centers_ buckets = [[] for _ in range(nlist)] for i, v in enumerate(vecs): cid = kmeans.predict([v])[0] buckets[cid].append(i) start = time.time() results = [] for q in queries: centroid_dists = np.linalg.norm(centroids - q, axis=1) probe_ids = np.argsort(centroid_dists)[:nprobe] candidates = [] for pid in probe_ids: candidates.extend(buckets[pid]) candidate_vecs = vecs[candidates] scores = candidate_vecs @ q top_k_local = np.argsort(-scores)[:k] top_k_global = [candidates[idx] for idx in top_k_local] results.append(top_k_global) elapsed = time.time() - start return results, elapsed def compare_engines(n_vecs=10000, dim=128, n_queries=100): """对比Flat和IVF的性能""" vecs = np.random.randn(n_vecs, dim).astype(np.float32) queries = np.random.randn(n_queries, dim).astype(np.float32) _, flat_time = benchmark_flat(vecs, queries) _, ivf_time = benchmark_ivf(vecs, queries) print(f'Flat: {flat_time*1000:.1f}ms, IVF: {ivf_time*1000:.1f}ms') print(f'IVF speedup: {flat_time/ivf_time:.1f}x') return flat_time, ivf_time
Flat暴力搜索:归一化向量后通过矩阵乘法计算所有内积,argsort取top-k。等价于Faiss IndexFlatIP。IVF索引构建:使用KMeans将向量空间划分为nlist个簇,每个向量分配到最近的簇。IVF查询:找到距离查询最近的nprobe个簇,只在候选簇内计算精确距离。在候选向量中计算内积并取top-k,映射回全局索引。对比函数:生成随机数据,分别运行Flat和IVF,对比延迟和加速比。
常见问答
ScaNN、Faiss、Milvus三者的核心定位差异是什么?
为什么ScaNN的精度最高但不适合大规模生产环境?
Faiss和Milvus的本质区别是什么?
如何选择向量检索引擎?
Milvus的存算分离架构有什么优势?
常见误区
误区认为ScaNN精度最高就适合所有场景
正解ScaNN单机无分布式能力,大规模生产环境需Milvus或Faiss加自研分布式层。精度只是选型的维度之一,还需考虑分布式能力、动态更新、运维成本等。
误区认为Faiss和Milvus功能完全等价
正解Faiss是库需自行管理数据持久化和分布式,Milvus是完整数据库提供CRUD和高可用。两者在架构层面有本质区别。
误区认为recall最高的引擎就是最佳选择
正解选型需综合考虑recall、延迟、内存、吞吐、数据规模和运维成本,不能只看单一指标。
误区认为向量数据库只是传统数据库加了向量字段
正解向量数据库在索引结构(ANN vs B+Tree)、查询模式(近似搜索 vs 精确匹配)、存储优化(列式压缩 vs 行存储)上与传统数据库有本质区别。
参考来源
- webpageScaNN: Anisotropic Vector Quantization for High-Precision Nearest Neighbor Search
- webpageFaiss: A Library for Efficient Similarity Search and Clustering of Vectors
- webpageMilvus: A Cloud-Native Vector Database
- webpageProduct Quantization for Nearest Neighbor Search
- webpageEfficient and Robust Approximate Nearest Neighbor Search Using HNSW Graphs