向量数据库选型:Milvus vs Qdrant vs Chroma实测对比

3 阅读3分钟

团队做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

单节点就这么简单。

性能对比实测

数据量ChromaQdrant
200万25ms8ms
500万80ms15ms
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"

避坑建议

  1. Chroma不要上生产——学习可以,真跑业务性能不够
  2. 别一上来选最重的方案——Qdrant能cover的话不需要Milvus
  3. 迁移成本想清楚——换数据库数据迁移挺折腾的
  4. 选型前先想清楚数据量和并发——比看功能列表管用