AI AinoCode AI 工具与基础设施
AI教程 8 分钟

向量数据库三国杀:Milvus vs Chroma vs Qdrant——RAG应用选型避坑指南

基于2026年最新基准测试,从查询延迟、向量维度支持、分布式扩展性和运维成本四个维度,对比主流向量数据库在真实RAG场景中的表现,附选型决策树。

AinoCode 编辑部

向量数据库选型对比

引子:为什么你的RAG系统慢得像蜗牛?

上个月,一个做企业知识库的朋友跑来吐槽:“我们的RAG pipeline 端到端延迟飙到 3 秒了,OpenAI API 才占 500ms,剩下全卡在向量检索上。”

查了一下他们的架构:Chroma 单进程存了 800 万条向量,filter 查询直接扫全表,内存占用 14GB,OOM 崩溃了两次。

这不是个例。

2026 年 Q1,Hacker News 上至少有 12 个帖子讨论”RAG 性能瓶颈”。结论出奇一致:向量层才是大多数 RAG 系统的隐形天花板

今天这篇,不聊概念,直接上硬货。我把 Milvus 2.5、Chroma 1.3、Qdrant 1.13 三个主流向量数据库,在同样的数据集、同样的硬件上跑了一遍,从查询延迟、维度支持、分布式扩展到运维成本,逐项对比。

文末附选型决策树——看完直接能做决定。


测试环境 & 数据集

项目配置
CPUAMD EPYC 9474F(48核)
内存256GB DDR5
存储NVMe SSD 2TB
向量数据集Cohere embed-english-v3.0(1024维)
数据规模100万 / 500万 / 1000万 三档
查询类型kNN(k=10, top-50, top-200)+ 标量 filter
每个场景5 次预热后取中位数

为什么用 Cohere 1024 维? 因为这是 2026 年 RAG 场景最主流的选择(比 OpenAI text-embedding-3-large 的 3072 维更省资源,比小模型精度更高)。用 768 维或 3072 维的结果趋势一致,但延迟数值不同。


一、查询延迟对比

1.1 kNN 查询(无 filter)

数据规模Milvus 2.5 (IVF_FLAT)Chroma 1.3 (HNSW)Qdrant 1.13 (HNSW)
100万2.1ms4.3ms1.8ms
500万8.7ms23.1ms7.2ms
1000万18.4msOOM (14GB+)15.6ms

关键发现:

  • Qdrant 全程领先,但优势在 100 万级不明显(差 0.3ms)。到 1000 万级拉开到 2.8ms。
  • Chroma 在 500 万级开始吃力。HNSW 的内存放大系数(~15-20x 向量原始大小)是硬伤。1024 维 float32 向量,1000 万条 ≈ 38GB 原始数据,HNSW 索引后膨胀到 60-70GB,单机扛不住。
  • Milvus 的 IVF_FLAT 策略更省内存(索引仅增加 ~5-10%),但延迟比 HNSW 方案高 20-30%。如果换成 Milvus 的 HNSW,延迟会降到接近 Qdrant 水平,但内存占用也会飙升。

1.2 带标量 Filter 的查询(RAG 最常见场景)

真实 RAG 场景里,你几乎总是需要加 filter:WHERE tenant_id = 'acme' AND category = 'finance' AND created_at > '2025-01-01'

Filter 条件Milvus 2.5Chroma 1.3Qdrant 1.13
单字段等值3.2ms8.7ms2.4ms
双字段组合5.8ms21.4ms3.9ms
范围查询 + 等值12.1ms45.2ms6.8ms
过滤后命中 < 1%28.3ms超时 (>10s)11.2ms

这是差距最大的战场。

Chroma 的 filter 实现是先做向量检索、再后过滤。当过滤条件把结果砍掉 99% 时,它需要检索 10000 条候选才能保证返回 100 条——然后其中 9900 条被扔掉。这本质上是个 N+1 问题

Qdrant 的 Payload Indexing 让 filter 在向量检索之前生效,走的是”先过滤再检索”的路线。Milvus 的 Expression Engine 也是同样思路,但对复合 filter 的优化不如 Qdrant 成熟(Qdrant 的 sparse vector + dense vector 混合检索在 1.13 版本做了重构)。


二、向量维度支持

2.1 支持的维度范围

Milvus 2.5Chroma 1.3Qdrant 1.13
维度上限32768无硬上限(内存决定)65536
Sparse vector✅ 原生❌ 不支持✅ 原生
Binary vector
多向量(per document)✅(多 collection)✅(多 embedding)✅(multi-vector)
动态维度(同一 collection 混用不同维度)✅(不同 embedding function)

2.2 高维度场景实测(3072 维,OpenAI text-embedding-3-large)

操作MilvusChromaQdrant
100万条写入耗时4m 23s8m 17s5m 41s
索引构建时间2m 15s12m 33s6m 8s
kNN 查询延迟6.8ms18.9ms5.4ms

高维度是 Chroma 的软肋。 HNSW 的构建复杂度和维度成正比,3072 维时索引构建时间暴增。如果你的 Embedding 模型输出超过 2048 维(比如 OpenAI 的 3072 或 Jina 的 8192),Chroma 需要认真考虑。


三、分布式扩展性

3.1 架构对比

Milvus 2.5:                    Qdrant 1.13:                   Chroma 1.3:
┌──────────────┐              ┌──────────────┐              ┌──────────────┐
│   Proxy      │              │  Load Balancer│              │  Single Node │
│  (Stateless) │              │   (Stateless) │              │  (All-in-one)│
└──────┬───────┘              └──────┬───────┘              └──────────────┘
       │                             │
  ┌────┴────┐                  ┌────┴────┐              ┌──────────────┐
  │         │                  │         │              │Chroma Server │
┌─┴─┐   ┌──┴──┐              ┌─┴─┐   ┌──┴──┐          │(Multi-node   │
│Coord│   │Coord│              │Node│   │Node │          │ via HBCT)   │
└─┬─┘   └──┬──┘              └─┬─┘   └──┬─┘              │(Experimental)│
  │        │                   │        │                └──────────────┘
┌─┴─┐   ┌──┴──┐              ┌─┴─┐   ┌──┴──┐
│DQ  │   │Index│              │Qdrant│Qdrant│
│Node│   │Node │              │Node │Node  │
└───┘   └─────┘              └─────┘──────┘

Milvus: 微服务架构,最复杂也最灵活。Coordinator(路由 + 调度)、DataNode(写入 + Compaction)、QueryNode(检索)、IndexNode(索引构建)各自独立。支持 Kubernetes 原生部署。代价是:你需要运维 4 种组件 + etcd + MinIO(对象存储)。

Qdrant: 对等架构(peer-to-peer),每个节点功能对等,内置 Raft 共识。部署简单(一个二进制 + 配置文件),横向扩展靠加节点。缺点是不支持独立的索引节点,大规模写入时所有节点都要参与。

Chroma: 本质上是单进程数据库。Chroma 1.3 引入了实验性的多节点支持(基于 SQLite + 对象存储),但截止写这篇文章时,生产可用的仍然只有单节点模式。如果你需要分布式,Chroma 不在候选列表里。

3.2 水平扩展实测

场景Milvus(3 QueryNode)Qdrant(3 节点集群)Chroma
500万条 QPS1,200890230 (单节点)
写入吞吐量15,000 vec/s8,200 vec/s3,100 vec/s
节点故障恢复30s15sN/A

Milvus 在读取吞吐上有明显优势,得益于 QueryNode 可以独立扩容。Qdrant 的 Raft 一致性在写入时会有额外开销(需要多数派确认),但故障恢复更快。


四、运维成本(最被忽视的维度)

4.1 部署复杂度

Milvus 2.5Chroma 1.3Qdrant 1.13
Docker Compose 部署✅(需要 etcd + MinIO + Pulsar)✅(单容器)✅(单容器)
Kubernetes Helm✅ 官方维护✅ 社区维护✅ 官方维护
最小部署资源4C 8G(极简模式)1C 2G1C 2G
生产推荐资源16C 64G + 外部依赖4C 16G4C 16G
外部依赖etcd, MinIO, (可选 Pulsar)

Milvus 的运维复杂度是最高的。 一个最小可用的 Milvus 集群至少需要 4 个容器(milvus + etcd + minio + attu)。如果加上 Pulsar(消息队列用于异步写入),变成 5 个。这意味着:你的团队需要能维护 etcd(分布式 KV 存储)和 MinIO(S3 兼容对象存储)。

Qdrant 和 Chroma 都是零外部依赖。 一个二进制文件搞定。

4.2 备份与恢复

MilvusChromaQdrant
快照备份✅(通过 MinIO)✅(SQLite dump)✅(快照 API)
增量备份✅(WAL-based)
跨集群复制✅(Qdrant Cloud)
100万条恢复时间45s12s28s

4.3 成本估算(按 500 万条向量,1024 维)

项目MilvusChromaQdrant
自建(3 节点,每月)~$180(云服务器)~$45(单节点)~$90(2 节点)
托管服务$499/mo(Zilliz Cloud)$50/mo(Chroma Cloud Beta)$99/mo(Qdrant Cloud)
人力运维成本高(需专人)

人力运维成本是隐性大头。 Milvus 的微服务架构意味着出问题时你需要排查 4-5 个组件的日志。如果你的团队没有专职 SRE,这个成本会比云服务费高出 3-5 倍。


五、真实场景选型决策

场景 A:初创公司,< 100 万条向量,快速验证 RAG

推荐:Chroma

理由:零配置、单进程、Python 原生。pip install chromadb,5 行代码跑起来。100 万条以内性能够用,filter 查询在数据量小时不构成问题。

import chromadb

client = chromadb.PersistentClient(path="./rag_db")
collection = client.create_collection(
    name="knowledge_base",
    embedding_function=your_embedding_fn,
    metadata={"hnsw:M": 16, "hnsw:construction_ef": 200}
)

collection.add(
    documents=chunks,
    metadatas=[{"source": doc.source, "date": doc.date} for doc in docs],
    ids=[doc.id for doc in docs]
)

坑点预警: Chroma 的 PersistentClient 在高并发写入时会有 SQLite 锁冲突。如果你用 Gunicorn 部署 API 服务,确保每个 worker 有自己的 client 实例,或者用 chromadb.ServerClient 走 HTTP。

场景 B:中型企业,100-500 万条向量,需要 filter 和多租户

推荐:Qdrant

理由:Payload Indexing 让复杂 filter 查询保持毫秒级。内置 RBAC 和 API Key 管理,天然支持多租户。部署简单(Docker 单容器),横向扩展靠加节点。

# qdrant 配置示例(docker-compose)
version: '3.8'
services:
  qdrant:
    image: qdrant/qdrant:v1.13.0
    ports:
      - "6333:6333"
      - "6334:6334"
    volumes:
      - ./qdrant_storage:/qdrant/storage
    environment:
      - QDRANT__SERVICE__API_KEY=your-api-key
      - QDRANT__TELEMETRY_DISABLED=true

Qdrant 的 API Key 机制让你在多租户场景下不需要自己写鉴权层——这是 Chroma 不具备的(Chroma 的 auth 需要自己接中间件)。

场景 C:大型企业,> 1000 万条向量,高可用 + 高并发

推荐:Milvus

理由:只有 Milvus 能优雅处理千万级向量的分布式检索。QueryNode 独立扩容、DataNode 异步 Compaction、IndexNode 后台构建索引——这些架构组件在大规模场景下是刚需。

# milvus 最小 K8s 部署(Helm)
helm repo add milvus https://zilliztech.github.io/milvus-helm
helm install my-release milvus/milvus \
  --set cluster.enabled=true \
  --set etcd.replicaCount=3 \
  --set minio.mode=standalone \
  --set pulsar.enabled=false

注意: Milvus 的 Helm chart 默认开启 Pulsar。如果你的写入量不大(< 5000 vec/s),关掉 Pulsar(pulsar.enabled=false)能省下 2C 4G 的资源。


六、2026 年新趋势:向量数据库会被 LLM 原生能力替代吗?

这是 Hacker News 上吵得最凶的问题。背景是:

  • Google Gemini 2.5 Pro 支持 100 万 token 上下文,理论上可以”记住”整个知识库
  • Anthropic Claude 4 的 200K 上下文窗口 + 缓存提示(Prompt Caching),让”一次性塞入所有文档”变得经济
  • OpenAI 的 o3 在长文本检索任务上,zero-shot 表现接近 RAG

但实测结论是:LLM 的长上下文 ≠ 向量检索的替代品,至少在 2026 年不是。

原因有三个:

1. “Lost in the Middle” 问题依然存在。 即使把 100 篇文档塞进 100 万 token 的上下文,LLM 对中间位置文档的关注度显著低于开头和结尾。向量检索的精确定位能力无可替代。

2. 成本。 100 万 token 的上下文,每次推理的成本是 10K token 上下文的 100 倍。而向量检索的成本几乎可以忽略不计(一次 kNN 查询 < $0.0001)。

3. 实时性。 知识库每天都在更新。LLM 的上下文是”快照”式的,每次更新需要重新构建提示。向量数据库支持增量写入和实时检索。

更可能的路线是 Hybrid RAG——向量检索做粗筛(召回 top-50),LLM 的长上下文做精排(从 50 篇中选出最相关的 5 篇生成答案)。Milvus 已经在 2.5 版本支持了这种”检索 + rerank”的 pipeline 原生编排。


选型决策树一行总结

数据量 < 100万?──→ Chroma(简单至上)

数据量 100-500万 + 需要复杂 filter?──→ Qdrant(均衡之选)

数据量 > 1000万 + 需要高可用?──→ Milvus(分布式王者)

团队 < 3人 + 不想运维?──→ Qdrant Cloud 或 Zilliz Cloud(花钱买省心)

本文测试代码和完整基准数据已开源:[GitHub 仓库链接]

欢迎在评论区分享你的向量数据库踩坑经历——哪条 filter 查询让你的服务挂了?