向量数据库选型与实践
FAISS / Chroma / Milvus / Qdrant / Pinecone / Weaviate 全面对比与选型指南
向量数据库 vs 传统数据库
传统关系型数据库(如 MySQL、PostgreSQL)基于精确匹配和范围查询,通过 B+ 树等索引结构加速检索。但当数据需要以"语义相似度"而非"精确值"来查询时,传统数据库便力不从心。
向量数据库专为高维向量数据的存储与相似性检索而设计。其核心能力在于:
- 语义搜索:将文本、图像、音频等非结构化数据编码为向量,通过余弦距离、欧氏距离或内积衡量语义相似度。
- 近似最近邻(ANN)检索:在大规模向量集合中,以极低精度损失换取数个数量级的检索速度提升,避免暴力穷举 O(n) 的时间复杂度。
- 混合检索:同时支持向量相似度与结构化字段过滤(如标量过滤、全文检索),满足复杂业务场景。
核心索引类型
向量数据库的性能瓶颈在于"维度灾难"——维度越高,数据越稀疏,暴力搜索的开销呈指数级上升。为此,业界发展出多种 ANN 索引结构。
IVF(倒排文件索引)
IVF(Inverted File Index)是最经典的 ANN 索引之一,核心思想是"先聚类,再搜索"。
工作原理:
- 使用 K-Means 对向量空间聚类,生成 nlist 个聚类中心(Voronoi 图)。
- 每个向量被分配到最近的聚类中心,建立倒排列表。
- 搜索时,计算查询向量与所有聚类中心的距离,选出最近的 nprobe 个簇,仅在对应桶内执行搜索。
关键参数:
- nlist:聚类中心数量。nlist 越大,每个桶内向量越少,建索引开销越大但检索精度越高。
- nprobe:搜索时探查的簇数量。nprobe 越大,召回率越高但延迟也越高。
变体:
- IVF-Flat:桶内存储原始向量,搜索时直接计算精确距离。精度高但内存开销大。
- IVF-PQ(乘积量化):桶内存储压缩后的量化编码,大幅降低内存占用,适合内存受限的大规模场景。召回率受量化精度影响。
# IVF 参数设置示意
index_ivf = faiss.IndexIVFFlat(quantizer, dimension, nlist=100)
index_ivf.nprobe = 10 # 搜索时探查 10 个簇HNSW(分层可导航小船世界图)
HNSW(Hierarchical Navigable Small World)是目前综合性能最优秀的 ANN 索引之一,广泛用于 Milvus、Qdrant、Chroma 等系统。
工作原理:
HNSW 构建一个多层图结构:
- 底层包含所有向量,越上层节点越稀疏。
- 搜索从顶层开始,在每一层使用贪婪算法找到局部最近邻,将其作为下一层的入口点。
- 类似"从卫星视图逐步放大到街景"的过程,大幅缩小搜索范围。
参数与性能关系:
| 参数 | 含义 | 对性能影响 |
|---|---|---|
| M | 每个节点的最大连接数 | M 越大,图连接越密,召回率提升,但建图时间和内存增大 |
| efConstruction | 建图时的动态列表大小 | 值越大,图质量越高,建索引越慢 |
| efSearch | 搜索时的动态列表大小 | 值越大,召回率越高,搜索延迟线性增加 |
HNSW 的典型优势在于无需训练(不像 IVF 需要 K-Means 聚类),建索引即插即用;且延迟和召回率在同参数下普遍优于 IVF。
其他索引
- DiskANN:基于 SSD 的大规模 ANN 索引,利用 Vamana 图和内存缓存,适合内存无法容纳全部向量的场景(十亿级以上)。典型实现如 Microsoft DiskANN、Qdrant 的部分存储后端。
- SCANN(Squared Cosine Approximate Nearest Neighbors):Google 提出的索引,结合了 PQ 量化和非对称距离计算(ADC),在精度和速度之间取得了优秀平衡,广泛用于 Google 内部搜索系统。
主流向量数据库/库对比
下表从多个维度对比当前主流的向量数据库与向量检索库。
| 维度 | FAISS | Chroma | Milvus | Qdrant | Pinecone | Weaviate |
|---|---|---|---|---|---|---|
| 定位 | 本地计算库 | 轻量嵌入式数据库 | 分布式向量数据库 | 高性能向量数据库 | 全托管向量数据库 | 云原生向量数据库 |
| 部署方式 | 进程内集成 | 嵌入式 / 客户端-服务端 | 分布式集群 | 单机 / 集群 | SaaS 全托管 | 自托管 / SaaS |
| 索引类型 | IVF, HNSW, PQ, LSH | HNSW | IVF, HNSW, DiskANN, SCANN | HNSW, 自定义多级索引 | 专有索引 | HNSW, 动态索引 |
| 分布式支持 | 不支持 | 有限(仅客户端模式) | 支持(分片+副本) | 支持(Raft 共识) | 原生支持 | 支持 |
| 云原生 | 否 | 否 | 是(K8s Operator) | 是(Docker/K8s) | 是 | 是 |
| 持久化 | 不支持 | 支持(SQLite 存储) | 支持(对象存储 + 本地盘) | 支持 | 支持 | 支持 |
| 混合检索 | 不支持 | 有限 | 支持(标量过滤 + 全文检索) | 支持(Payload 过滤 + 全文) | 支持(Metadata 过滤) | 支持(GraphQL + 向量) |
| 开源许可 | MIT | Apache 2.0 | Apache 2.0 | Apache 2.0 | 闭源 | BSD-3 Clause |
| 语言 | C++ / Python | Python | Go / Java / Python | Rust | 专有 | Go |
| 社区活跃度 | 高(Meta) | 高 | 高(LF AI & Data) | 中高 | N/A | 中高 |
选型指南
原型开发 / 快速验证
推荐 FAISS + Chroma。FAISS 提供最丰富的索引算法支持,Chroma 提供极简的 API 和零配置体验,适合在小规模数据集上快速验证 RAG(检索增强生成)流程。
pip install faiss-cpu chromadb生产部署 / 百万级规模
推荐 Qdrant 或 Milvus。Qdrant 使用 Rust 编写,单机性能极强,部署运维简洁;Milvus 生态丰富,适合需要 GPU 加速或复杂分片策略的场景。
- Qdrant 适合:对延迟敏感、资源可控的中等规模生产环境。
- Milvus 适合:需要 GPU 加速、多级存储、复杂混合查询的企业级场景。
亿级规模 / 超大数据集
推荐 Milvus 或 Pinecone。Milvus 的分片与多级存储(内存 + SSD + 对象存储)可水平扩展至百亿级别;Pinecone 提供无需运维的全托管方案,但成本较高。
DiskANN 类索引是亿级规模下的关键——单机内存无法容纳全部向量时,基于 SSD 的索引成为唯一可行方案。
低延迟 / 高并发
推荐 Qdrant(Rust 原生)或 Pinecone(托管优化)。Qdrant 的零 GC 与高效内存管理使其在 p99 延迟上表现优异。
多模态 / 混合搜索
推荐 Weaviate 或 Milvus。Weaviate 原生支持 GraphQL 接口和多模态向量化(通过模块化集成 OpenAI、Cohere、HuggingFace 等推理服务),Milvus 支持丰富的混合查询与标量过滤能力。
实践代码
FAISS 示例:IVF-PQ 索引
import numpy as np
import faiss
# 生成模拟数据:10000 条 128 维向量
dimension = 128
database_vectors = np.random.random((10000, dimension)).astype("float32")
query_vector = np.random.random((1, dimension)).astype("float32")
# 构建 IVF-PQ 索引
# 1. 创建量化器(使用 Flat 量化器作为聚类基础)
quantizer = faiss.IndexFlatL2(dimension)
# 2. 创建 IVF-PQ 索引:nlist=100, M=16(每个子向量 16 个码字), nbits=8
index = faiss.IndexIVFPQ(quantizer, dimension, nlist=100, M=16, nbits=8)
# 3. 训练索引(IVF 需要训练 K-Means 聚类器)
assert index.is_trained is False
index.train(database_vectors)
assert index.is_trained is True
# 4. 添加向量
index.add(database_vectors)
# 5. 搜索:返回 top-5 最近邻
k = 5
index.nprobe = 10 # 设置搜索时探查的簇数
distances, indices = index.search(query_vector, k)
print(f"查询向量维度: {dimension}")
print(f"搜索结果索引: {indices}")
print(f"对应距离: {distances}")
print(f"索引总向量数: {index.ntotal}")FAISS 示例:HNSW 索引
import faiss
import numpy as np
# 生成数据
dimension = 128
data = np.random.random((50000, dimension)).astype("float32")
# 构建 HNSW 索引
index = faiss.IndexHNSWFlat(dimension, M=32)
index.hnsw.efConstruction = 200 # 建图质量
index.add(data)
# 搜索
index.hnsw.efSearch = 64 # 搜索深度
queries = np.random.random((10, dimension)).astype("float32")
distances, indices = index.search(queries, k=10)
print(f"HNSW 搜索完成,返回形状: {indices.shape}")Chroma 示例:创建集合与相似搜索
import chromadb
from chromadb.config import Settings
import numpy as np
# 1. 初始化客户端(内存模式,无需外部服务)
client = chromadb.Client(Settings(
chroma_db_impl="duckdb+parquet",
anonymized_telemetry=False,
))
# 2. 创建集合
collection = client.create_collection(
name="tech_articles",
metadata={"hnsw:space": "cosine"}, # 使用余弦距离
)
# 3. 添加文档(自动编码为向量)
documents = [
"向量数据库在 RAG 应用中扮演核心角色",
"HNSW 索引在图结构中实现高效搜索",
"Milvus 支持 GPU 加速和分布式部署",
"Qdrant 使用 Rust 语言编写,性能优异",
"Pinecone 提供全托管的向量数据库服务",
]
ids = [f"doc_{i}" for i in range(len(documents))]
collection.add(
documents=documents,
ids=ids,
)
# 4. 相似搜索
query = "推荐使用的向量数据库"
results = collection.query(
query_texts=[query],
n_results=3,
)
print(f"查询: {query}")
print(f"结果数量: {len(results['documents'][0])}")
for i, (doc, dist) in enumerate(
zip(results["documents"][0], results["distances"][0])
):
print(f" [{i}] 距离={dist:.4f} | {doc}")Chroma 示例:客户端-服务端模式
import chromadb
# 连接远程 Chroma 服务
client = chromadb.HttpClient(host="localhost", port=8000)
# 获取或创建集合
collection = client.get_or_create_collection(name="production_vectors")
# 自定义向量(而非自动编码)
import numpy as np
vectors = np.random.random((100, 768)).astype("float32").tolist()
metadata = [{"source": f"file_{i}", "tag": "embedding"} for i in range(100)]
collection.add(
embeddings=vectors,
metadatas=metadata,
ids=[f"vec_{i}" for i in range(100)],
)
# 带标量过滤的搜索
results = collection.query(
query_embeddings=[np.random.random(768).tolist()],
n_results=5,
where={"tag": "embedding"}, # 仅过滤 tag 为 embedding 的结果
)
print(f"过滤后结果数: {len(results['ids'][0])}")总结
向量数据库的选型并非"唯性能论",需要结合团队技术栈、运维能力、数据规模和业务延迟要求综合考量:
- 个人/小团队原型验证:FAISS + Chroma,快速迭代、零运维。
- 中等规模生产环境:Qdrant,Rust 带来的极致性能和简洁部署。
- 企业级大规模部署:Milvus,丰富的索引类型和成熟的分布式生态。
- 全托管免运维:Pinecone,适合快速上线的商业项目。
- 多模态云原生场景:Weaviate,GraphQL 原生支持与模块化推理集成。
无论选择何种方案,理解 ANN 索引的底层原理(IVF 的聚类搜索、HNSW 的分层图结构、PQ 的量化压缩)都是做出正确技术判断的基础。