常用向量数据库怎么选型?

#RAG#Agent#面试八股

常用向量数据库怎么选型?

结论:选型看四个约束——数据规模、过滤复杂度、运维能力、生态耦合,而不是看 benchmark 排名。 已有 PostgreSQL 且数据在千万级以下,pgvector 最省事;要"关键词 + 向量"一体,选 Elasticsearch/OpenSearch; 上亿级或高并发写入,才轮到 Milvus、Qdrant 这类专用库;完全不想碰运维,就走托管服务。

1. 候选清单与定位

方案形态强项短板适合
pgvectorPostgreSQL 扩展零新增组件、SQL 过滤、事务一致千万级以上吃紧,索引重建慢已有 PG、百万级
Elasticsearch / OpenSearch搜索引擎BM25 与 kNN 同库、聚合分析成熟向量性能非专精,堆内存开销大混合检索为主
Milvus分布式专用库亿级规模、多种索引、可上 GPU依赖 etcd/对象存储,运维重平台型、大规模
Qdrant专用库(Rust)过滤性能好、部署简单、payload 灵活生态相对年轻中小团队自建
Weaviate专用库内置向量化模块、GraphQL 接口资源占用偏高快速搭原型
Chroma嵌入式开发体验最好,几行代码起服务规模化与高可用弱POC、本地实验
Pinecone / Zilliz Cloud托管服务免运维、弹性伸缩成本、数据出域合规无基础设施团队

2. 决策树

已有 PostgreSQL?
├─ 是,且片段数 < 1000 万 ──────────▶ pgvector(省一个组件就是省钱)
└─ 否
   ├─ 需要 BM25 + 向量混合 ─────────▶ Elasticsearch / OpenSearch
   ├─ 片段数 > 5000 万 或 写入 QPS 高 ─▶ Milvus / Qdrant 集群
   ├─ 合规不允许数据出域 ───────────▶ 自建 Qdrant / Milvus
   └─ 团队没有运维 ─────────────────▶ 托管服务

3. 关键维度横向对比

维度pgvectorElasticsearchMilvusQdrant
典型规模百万~千万千万~亿亿级以上千万~亿
过滤 + ANNSQL WHERE,成熟filter 上下文,成熟标量过滤,支持payload 过滤,强
混合检索需自己拼 BM25原生 BM25 + kNN需外挂稀疏向量支持稀疏向量
事务完整 ACID无跨文档事务无无
运维复杂度低(复用 PG)中高低~中
主要索引HNSW / IVFFlatHNSWHNSW/IVF/PQ/DiskANNHNSW

数字只是量级参考,真实上限取决于维度、副本数、过滤选择性和硬件,务必用自己的数据压测。

4. 代码:同一件事,两种写法

# Qdrant:建集合 + 建 payload 索引 + 带过滤检索
from qdrant_client import QdrantClient, models

client = QdrantClient(url="http://localhost:6333")
client.recreate_collection(
    collection_name="kb",
    vectors_config=models.VectorParams(size=1536, distance=models.Distance.COSINE),
)
# 过滤字段一定要建索引,否则过滤退化成逐条扫描
client.create_payload_index("kb", field_name="source", field_schema=models.PayloadSchemaType.KEYWORD)

client.upsert("kb", points=[
    models.PointStruct(id=i, vector=vec, payload={"text": txt, "source": src})
    for i, (vec, txt, src) in enumerate(zip(vectors, texts, sources))
])

hits = client.search(
    collection_name="kb", query_vector=qvec, limit=20, with_payload=True,
    query_filter=models.Filter(must=[
        models.FieldCondition(key="source", match=models.MatchValue(value="employee-handbook"))
    ]),
)
-- pgvector:同样的语义,用 SQL 表达,还能直接 JOIN 业务表
SELECT c.id, c.content, 1 - (c.embedding <=> $1) AS score
FROM doc_chunk c
JOIN doc_meta m ON m.source = c.source
WHERE m.tenant_id = $2 AND m.status = 'active'
ORDER BY c.embedding <=> $1
LIMIT 20;

5. 迁移与避坑清单

坑说明
距离度量混用建库用 cosine、查询用 L2,结果全乱;三者(模型、归一化、度量)必须成套迁移
维度不一致换 embedding 模型必须重建集合,不能只改配置
过滤字段没索引Qdrant 的 payload 索引、Milvus 的标量索引,漏建就是全扫
写入可见延迟部分库是近实时,写完立刻查可能查不到,压测时要算进去
删除不回收软删除堆积会让召回和内存一起退化,定期 compaction

工程上建议抽一个 VectorStore 接口(upsert / query / delete / health),把 SDK 调用收敛到一处,换库时只改适配层。

6. 常见追问

Q:pgvector 到底能撑多大? 百万级很稳;千万级要分区、调 maintenance_work_mem、接受更长的索引构建时间;再往上不如换专用库,别硬扛。

Q:为什么 Elasticsearch 的向量检索不如专用库? 段(segment)结构、堆内存模型和近实时刷新机制不是为向量设计的,图索引构建与合并成本更高。

Q:多租户怎么隔离? 租户少用独立集合,租户多用 payload 字段过滤 + 路由;隔离性和成本要权衡,别一上来就"每租户一集合"。

Q:能不能自己包一层 FAISS? 只有在极端性能需求、且团队愿意自己处理持久化、增删、副本、故障恢复时才考虑,通常不划算。

小结

选型的正确答案往往是最"无聊"的那个:能复用现有基础设施、过滤够用、运维扛得住,就是好选择。把省下的精力投到分块和评估上,回报更高。

笔记加载中…