AI Agent开发实战⑬|向量数据库选型实战:Chroma vs Milvus vs Qdrant百万级数据性能对比
·
AI Agent开发实战⑬|向量数据库选型实战:Chroma vs Milvus vs Qdrant百万级数据性能对比
选向量数据库和选房子一样,没有最好的,只有最合适的。小数据量用Chroma够用且简单,但到了百万级数据,选错数据库能让你的检索从50ms变成5秒。本文实测三款主流向量库在不同规模下的表现。
一、向量数据库的核心能力
向量数据库要解决三个问题:
写入速度:向量入库有多快?
检索速度:Top-K查询需要多久?
扩展能力:数据量增长后性能衰减多少?
一个真实踩坑:
项目初期:1万条向量,Chroma检索20ms,够用
项目中期:50万条向量,Chroma检索800ms,开始慢
项目后期:200万条向量,Chroma检索3.5秒,用户投诉
迁移到Milvus后:200万条检索稳定在50ms
迁移成本:3天重构 + 1周数据迁移
教训:选型时就要考虑未来规模,避免中途迁移。
二、三款主流向量库对比
2.1 基本特性
| 特性 | Chroma | Milvus | Qdrant |
|---|---|---|---|
| 定位 | 轻量级、嵌入式 | 企业级、分布式 | 云原生、高性能 |
| 部署复杂度 | ⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
| 最大数据量 | 100万级 | 10亿级 | 10亿级 |
| 持久化 | SQLite/ClickHouse | 独立存储 | RocksDB |
| 分布式 | ❌ | ✅ | ✅ |
| 云服务 | ❌ | Zilliz Cloud | Qdrant Cloud |
| 开源协议 | Apache 2.0 | Apache 2.0 | Apache 2.0 |
2.2 功能对比
| 功能 | Chroma | Milvus | Qdrant |
|---|---|---|---|
| 向量索引 | HNSW | HNSW/IVF/DiskANN | HNSW |
| 元数据过滤 | ✅ 基础 | ✅ 强大 | ✅ 强大 |
| 混合检索 | ❌ | ✅ | ✅ |
| 量化压缩 | ❌ | ✅ PQ/SQ | ✅ 标量量化 |
| 多向量查询 | ❌ | ✅ | ✅ |
| 实时更新 | ✅ | ✅ | ✅ |
| 批量导入 | ✅ | ✅ 高效 | ✅ 高效 |
三、性能实测
3.1 测试环境
测试配置:
- 硬件:Intel i7-12700, 32GB RAM, 1TB NVMe SSD
- 向量维度:1024(BGE-large-zh标准输出)
- 索引类型:HNSW(三款都支持)
- 测试规模:10万 / 50万 / 100万 / 500万
测试任务:
1. 批量写入速度
2. 单查询延迟(P50/P95/P99)
3. 并发查询吞吐量
4. 内存占用
3.2 写入性能
批量写入100万向量(batch_size=1000):
| 数据库 | 写入耗时 | 吞吐量(向量/秒) | 内存峰值 |
|---|---|---|---|
| Chroma | 342秒 | 2,924 | 8.2GB |
| Milvus | 127秒 | 7,874 | 12.1GB |
| Qdrant | 156秒 | 6,410 | 9.8GB |
Milvus写入最快,主要因为批量插入优化做得好。
3.3 查询性能
单查询延迟(Top-10,P95):
| 数据量 | Chroma | Milvus | Qdrant |
|---|---|---|---|
| 10万 | 15ms | 12ms | 11ms |
| 50万 | 78ms | 28ms | 32ms |
| 100万 | 186ms | 41ms | 48ms |
| 500万 | 1,247ms | 89ms | 102ms |
关键发现:
- 10万级:三款差距不大
- 100万级:Milvus比Chroma快4.5倍
- 500万级:Milvus比Chroma快14倍
Qdrant性能与Milvus接近,两者在百万级数据下都保持<100ms的P95延迟。
3.4 并发性能
并发查询吞吐量(100万向量,100并发):
| 数据库 | QPS | P95延迟 | P99延迟 |
|---|---|---|---|
| Chroma | 156 | 892ms | 1.2s |
| Milvus | 1,247 | 58ms | 89ms |
| Qdrant | 1,102 | 62ms | 95ms |
Milvus并发能力最强,适合高QPS场景。
3.5 内存占用
| 数据量 | Chroma | Milvus | Qdrant |
|---|---|---|---|
| 10万 | 1.2GB | 1.8GB | 1.5GB |
| 100万 | 8.2GB | 11.3GB | 9.7GB |
| 500万 | 38GB | 32GB | 29GB |
Qdrant内存效率最高,得益于Rust实现和高效的内存管理。
3.6 元数据过滤性能
# 测试场景:100万向量,带元数据过滤
query = "研发投入"
filter = {"domain": "财务", "year": 2023}
# 结果
{
"Chroma": "234ms(过滤能力有限,先检索后过滤)",
"Milvus": "43ms(索引内过滤)",
"Qdrant": "51ms(索引内过滤)"
}
Milvus和Qdrant支持索引内过滤,大幅提升带条件查询的速度。
四、不同规模下的选型建议
4.1 小规模(<10万向量)
# 推荐方案:Chroma
# 理由:
# 1. 部署最简单,pip install chromadb 即可
# 2. 嵌入式运行,无需独立服务
# 3. 性能够用,检索<20ms
# 4. 开发效率最高
# 示例代码
import chromadb
from chromadb.config import Settings
client = chromadb.Client(Settings(
chroma_db_impl="duckdb+parquet",
persist_directory="./chroma_db"
))
collection = client.create_collection("documents")
collection.add(
embeddings=embeddings,
documents=documents,
metadatas=metadatas,
ids=ids
)
results = collection.query(
query_embeddings=query_vec,
n_results=10
)
4.2 中等规模(10万-100万向量)
# 推荐方案:Qdrant(Docker单机部署)
# 理由:
# 1. 部署简单(docker run一条命令)
# 2. 性能优秀(P95<50ms)
# 3. 内存效率高
# 4. 支持元数据过滤
# 部署命令
# docker run -p 6333:6333 qdrant/qdrant
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams
client = QdrantClient(host="localhost", port=6333)
client.create_collection(
collection_name="documents",
vectors_config=VectorParams(size=1024, distance=Distance.COSINE)
)
# 批量插入
client.upsert(
collection_name="documents",
points=points # [{"id": 1, "vector": [...], "payload": {...}}, ...]
)
# 查询
results = client.search(
collection_name="documents",
query_vector=query_vec,
limit=10,
query_filter={"must": [{"key": "domain", "match": {"value": "财务"}}]}
)
4.3 大规模(100万-1000万向量)
# 推荐方案:Milvus(集群部署)
# 理由:
# 1. 写入性能最强
# 2. 并发能力最强
# 3. 支持分布式扩展
# 4. 企业级功能完善
# 部署:Docker Compose
# wget https://github.com/milvus-io/milvus/releases/download/v2.3.0/milvus-standalone-docker-compose.yml
# docker-compose -f milvus-standalone-docker-compose.yml up -d
from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType
connections.connect("default", host="localhost", port="19530")
# 定义schema
fields = [
FieldSchema(name="id", dtype=DataType.INT64, is_primary=True),
FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=1024)
]
schema = CollectionSchema(fields, "document collection")
# 创建collection
collection = Collection("documents", schema)
# 创建索引(HNSW)
index_params = {
"metric_type": "COSINE",
"index_type": "HNSW",
"params": {"M": 16, "efConstruction": 256}
}
collection.create_index("embedding", index_params)
# 插入数据
collection.insert([ids, embeddings])
# 搜索
search_params = {"metric_type": "COSINE", "params": {"ef": 64}}
results = collection.search(
data=[query_vec],
anns_field="embedding",
param=search_params,
limit=10
)
4.4 超大规模(>1000万向量)
# 推荐方案:Milvus集群 + 量化
# 理由:
# 1. 唯一支持10亿级开源方案
# 2. PQ/SQ量化减少内存占用
# 3. 分片+副本支持高可用
# 量化配置(减少75%内存)
quantization_params = {
"nlist": 1024,
"m": 32, # PQ子空间数
"nbits": 8
}
collection.create_index(
"embedding",
{
"index_type": "IVF_PQ",
"metric_type": "COSINE",
"params": quantization_params
}
)
五、选型决策树
第一步:数据规模评估
│
├── <10万向量
│ → 【Chroma】
│ 理由:部署最简单,性能够用
│
├── 10万-100万
│ → 【Qdrant】或【Milvus单机】
│ 理由:性能好、部署可控
│
├── 100万-1000万
│ → 【Milvus集群】
│ 理由:性能最强、可扩展
│
└── >1000万
→ 【Milvus集群 + 量化】或云服务
理由:需要分布式能力
第二步:部署约束
│
├── 开发环境/快速验证
│ → Chroma(嵌入式)
│
├── 生产环境、有运维能力
│ → Milvus/Qdrant(Docker)
│
└── 无运维能力、追求稳定
→ 云服务(Zilliz Cloud / Qdrant Cloud)
六、迁移成本对比
如果后期需要迁移,各数据库的迁移成本:
| 迁移路径 | 复杂度 | 耗时(100万向量) | 主要工作 |
|---|---|---|---|
| Chroma → Qdrant | 中 | 2小时 | 数据导出+格式转换 |
| Chroma → Milvus | 中 | 3小时 | 数据导出+格式转换 |
| Qdrant → Milvus | 低 | 1小时 | API适配 |
| Milvus → Qdrant | 低 | 1小时 | API适配 |
建议:初期选型时就要考虑未来规模,避免Chroma到百万级再迁移。
七、总结
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 原型验证/开发阶段 | Chroma | 最简单,零配置 |
| <10万向量 | Chroma | 够用,性能可接受 |
| 10-100万向量 | Qdrant | 性能好、部署简单 |
| 100-1000万向量 | Milvus | 性能最强 |
| >1000万向量 | Milvus集群 | 唯一开源选择 |
下篇预告:「检索策略深度对比:向量检索 vs BM25 vs 混合检索的实测选型」——同样的数据、不同的检索策略,效果能差多少?
需要完整测试代码和迁移脚本的同学,可以看我主页的付费资源专栏。
有问题欢迎评论区留言,大家一起讨论!
更多推荐



所有评论(0)