团队做RAG系统,第一件事就是选向量数据库。调研两周,上生产后又踩了一轮,把经验整理出来给各位避避坑。
选型背景
我的场景:
- 内部知识库问答系统
- 文档量200万条,切完chunk向量1500-2000万
- 团队6人,无专职DBA
结论先行
| 数据库 | 适用规模 | 优点 | 缺点 |
|---|---|---|---|
| Chroma | <200万 | 上手快,零配置 | 并发差,大数据量性能下降 |
| Qdrant | 千万级 | 性能稳,配置灵活 | 集群有学习曲线 |
| Milvus | 亿级以上 | 扩展能力强,功能全 | 运维复杂 |
Chroma:入门首选,上生产劝退
快速上手
import chromadb
client = chromadb.Client()
collection = client.create_collection("my_kb")
collection.add(
embeddings=[[1.0, 2.0, 3.0]],
documents=["doc1", "doc2"],
ids=["id1", "id2"]
)
results = collection.query(
query_embeddings=[[1.0, 2.0, 3.0]],
n_results=5
)
几行代码就能跑,半小时搭完demo。
踩坑实录
并发问题:Python客户端用SQLite后端,写操作有锁,高并发直接爆。
性能随数据量下降:
| 数据量 | 查询延迟 |
|---|---|
| 200万 | 25ms |
| 500万 | 80ms |
| 800万+ | 开始超时 |
内存碎片化:服务跑一周左右偶发超时,重启治标不治本。
适用场景
- 本地开发验证
- 小规模(<200万向量)低并发场景
- 学习研究
Qdrant:中等规模最优解
为什么选Qdrant
调研了Qdrant和Weaviate。Weaviate功能更全,但对我这场景过于复杂。Qdrant"刚刚好"——功能够用,文档清晰,不会让你在配置项里选择困难。
Docker部署
docker run -p 6333:6333 \
-v $(pwd)/qdrant_storage:/qdrant/storage \
qdrant/qdrant
单节点就这么简单。
性能对比实测
| 数据量 | Chroma | Qdrant |
|---|---|---|
| 200万 | 25ms | 8ms |
| 500万 | 80ms | 15ms |
| 1000万 | 超时 | 25ms |
Qdrant用了HNSW + 量化(PQ)优化,大数据量下稳得多。
关键配置
# qdrant-standalone.yaml
hnsw_config:
m: 16 # 连接数,越大越准越占内存
ef_construct: 128 # 索引质量
quantization:
scalar:
type: int8 # int8量化,压缩75%存储
m和ef_construct是性能关键。开了量化后大概有2-3%的召回率下降,场景能接受。
适用场景
- 千万级向量
- 中等并发需求
- 需要一定定制化
- 跨语言团队(gRPC支持好)
Milvus:大规模首选,但不是必须
什么时候选Milvus
- 亿级向量以上
- 需要横向扩展能力
- 有强一致性需求
- 有专职运维团队
我的替代方案
没用Milvus,用Qdrant+手动分片代替。
按业务维度分Collection,每个<500万:
async def query_across_shards(query: str, top_k: int = 5):
"""跨Collection查询"""
tasks = [
collection_a.query(query, top_k),
collection_b.query(query, top_k),
collection_c.query(query, top_k),
]
results = await asyncio.gather(*tasks)
# 合并去重
merged = [r for result in results for r in result]
return sorted(merged, key=lambda x: x.score, reverse=True)[:top_k]
决策代码
def select_vector_db(data_size: int, has_dedicated_ops: bool) -> str:
"""
数据量单位:向量条数
"""
if data_size < 2_000_000:
return "Chroma"
elif data_size < 100_000_000 or not has_dedicated_ops:
return "Qdrant"
else:
return "Milvus"
避坑建议
- Chroma不要上生产——学习可以,真跑业务性能不够
- 别一上来选最重的方案——Qdrant能cover的话不需要Milvus
- 迁移成本想清楚——换数据库数据迁移挺折腾的
- 选型前先想清楚数据量和并发——比看功能列表管用