事情是这样的。
上一篇文章聊完三层检索策略之后,我盯着终端里的 docker ps 出神——里面躺着一个 Qdrant 容器,跑了快一个月,CPU 占用稳如老狗,但我一次查询都没往它那边发。
因为我发现我的 Chroma 跑得好好的。240 篇文章,5877 个 chunk,查询延迟没超过 1 秒,内存不到 200MB。我到底为什么要多维护一个独立服务?
这个念头一起,我就把 Qdrant 容器停了。然后花了一个下午把两个引擎的对比数据整理成这篇。先说结论:大多数人刚起步就想着"未来规模化",在主业内容都没跑通的时候,先把基础设施搭得跟大厂一样——这条路我见过太多次了,结局都一样:精力全耗在运维上,知识库本身没做起来。
如果你不想看完全文,这里是一张懒人决策表:
你的场景 | 推荐方案 | 一句话理由 |
|---|---|---|
个人知识库,内容 < 1 万篇 | ChromaDB | pip install 就完事,零运维 |
小团队共享(< 5 人) | ChromaDB | 每人本地跑自己的实例,不存在并发问题 |
团队协作(多人同时检索) | Qdrant | 独立服务,HTTP/gRPC 天然支持多客户端 |
内容库 > 5 万篇 | Qdrant | 量化压缩省内存,HNSW 在大规模下更稳 |
需要 Web Dashboard 监控 | Qdrant | 自带 Dashboard,Chroma 没有 |
非技术人员 / 不想折腾 | Notion AI / 飞书智能伙伴 | 开箱即用,但你会付出数据控制权的代价 |
如果看到这里你已经知道该选什么了,可以直接跳到「什么时候该迁移」那节——那部分才是真正值钱的东西。如果你还想知道"为什么"而不是"是什么",那咱们接着聊。
先说一个大前提:Chroma 和 Qdrant 虽然都是向量数据库,但它们的设计假设完全不同——就像一个螺丝刀和一个电钻,都能拧螺丝,但一个设计给偶尔修个家具的人,另一个设计给一天拧 500 颗螺丝的工人。
ChromaDB 的设计哲学:嵌入式优先。
Chroma 把自己定位成"AI 原生数据库"——这话翻译成人话就是:它假设你在写 Python,在做 AI 相关的活,而且不想花时间折腾数据库。它的核心 API 只有五个方法:add、query、get、update、delete。对,就五个。如果你用过 sqlite3,对 Chroma 的感觉应该很熟悉——import 一个包,创建一个 client,就可以开始干活了,进程退出数据还在。
Chroma 的架构也很简单:它默认用 HNSW(Hierarchical Navigable Small World)做近似最近邻搜索,距离度量默认余弦相似度。数据存在本地文件系统,索引全在内存里。没有 master-slave,没有分片,没有共识协议——它就是一个单机的、嵌入式的向量检索引擎。
这决定了它的上限和下限都很明确:下限极低(安装成本几乎为零),上限也有限(10 万向量以内性能稳定,超出后没有横向扩展路径)。

ChromaDB 嵌入式架构:Python 进程内运行,HNSW 索引全在内存,数据持久化到本地磁盘
Qdrant 的设计哲学:性能优先,独立服务。
Qdrant 是用 Rust 写的——从 87.3% 的代码占比就能看出来,作者对性能有执念。它把自己定位成一个"向量搜索引擎",对标的是 Elasticsearch 在文本搜索领域的地位。这意味着它从一开始就按独立服务来设计的:HTTP REST API、gRPC 接口、Web Dashboard、访问控制、快照备份——这些 Chroma 没有的东西,Qdrant 都有。
Qdrant 的索引同样基于 HNSW,但它多了一层量化压缩(Scalar Quantization / Product Quantization),可以把向量从 float32 压缩到 uint8 甚至更低精度,官方数据说最多能省 97% 的内存。它还支持 GPU 加速索引构建、io_uring 异步 I/O、WAL(Write-Ahead Log)保证数据可靠性——这些都是在"真·生产环境"里才能体现出价值的东西。
代价也很明显:你得维护一个独立进程。Docker 部署是最简单的,但生产环境你还得考虑健康检查、日志轮转、备份策略、版本升级。如果只有你一个人用,这些维护成本远大于性能收益。

Qdrant 独立服务架构:Rust 编写,HTTP/gRPC 通信,支持量化压缩与 GPU 加速
这一段是说给正在做选型的人听的——不是参数对比,是"你真的打开终端之后会发生什么"的真实流程。
ChromaDB:一条命令开始干活。
pip install chromadb
没了。然后你就可以在 Python 里写了:
import chromadb
client = chromadb.PersistentClient(path="./my_kb")
collection = client.get_or_create_collection("articles")
# 添加文档
collection.add(
documents=["Redis 是一个基于内存的键值数据库..."],
ids=["doc_001"]
)
# 查询
results = collection.query(
query_texts=["Redis 持久化机制"],
n_results=3
)
整个过程从 pip install 到第一条查询结果回来,不超过 3 分钟。不需要 Docker,不需要配端口,不需要考虑服务有没有启动——Chroma 在你启动 Python 脚本的那一刻就开始工作了。
Qdrant:Docker 拉起来,但你得知道自己在干嘛。
docker run -p 6333:6333 -p 6334:6334 \
-v $(pwd)/qdrant_storage:/qdrant/storage:z \
qdrant/qdrant
好,容器起来了。现在你有了一个跑在 6333 端口的 REST API 服务和一个跑在 6334 端口的 gRPC 服务。然后呢?你得装客户端:
pip install qdrant-client
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams
client = QdrantClient(host="localhost", port=6333)
# 创建 collection
client.create_collection(
collection_name="articles",
vectors_config=VectorParams(size=768, distance=Distance.COSINE)
)
# 添加文档
client.upsert(
collection_name="articles",
points=[{
"id": 1,
"vector": embedding, # 你得先自己生成 embedding
"payload": {"text": "Redis 是一个基于内存的键值数据库..."}
}]
)
注意这里的一个关键差异:Chroma 内置了 embedding 函数(你可以传文本,它帮你向量化),而 Qdrant 需要你自己先搞定 embedding,它只负责存储和检索向量。这对新手来说是额外的认知负担。
真实感受:我第一轮折腾的时候,Qdrant 的 Docker 拉起来之后,花了大概 20 分钟看文档才搞清楚 collection 参数怎么配、向量维度必须预先指定、upsert 的 payload 结构。而 Chroma 从零到跑通大概花了 3 分钟。这个差距在一个人项目里几乎可以忽略——但在你同时维护代码、写文章、做内容的时候,它就是"今天收工前顺手试一下"和"算了明天再搞"的区别。
一句话总结:Chroma 的上手成本约等于零,Qdrant 需要你具备"维护一个服务"的认知成本。 这两个成本在不同阶段权重不同——起步期,前者的价值远大于后者。
说到性能,我得先说一个大实话:99% 讨论向量数据库性能的文章,都是在讨论你不会遇到的规模。
Qdrant 官方 benchmark 显示,它在百万级向量上的查询延迟可以控制在 10ms 以内,配合量化压缩后内存占用能压到同等精度方案的 3%。这些数字是真的——但前提是你真的有百万级向量。我用 240 篇文章跑出来的 5877 个 chunk,在这个数量级下,两个方案的性能差异你根本感知不到。
我实际测试的结果(环境:MacBook Pro M1,16GB RAM,embedding 维度 384):
指标 | ChromaDB | Qdrant |
|---|---|---|
首次导入 5877 chunks | ~12 秒 | ~8 秒 |
单次查询延迟(P50) | 0.3s | 0.1s |
单次查询延迟(P99) | 0.8s | 0.3s |
空闲内存占用 | ~180MB | ~350MB |
启动时间 | 即开即用 | Docker 启动 ~5s |
Qdrant 确实更快——但在 5000 级别 chunks 上,0.8 秒和 0.3 秒的差异,对一个人读知识库的场景来说,毫无意义。你根本感觉不到。
但故事到了另一个规模就不一样了。如果你的知识库有 10 万篇文章、超过 50 万个 chunks,Chroma 的 HNSW 索引全部驻留在内存里,按 384 维 float32 向量计算,光索引就要占用约 800MB 内存,加上原始数据和中间计算结果,很容易突破 2GB。而 Qdrant 的量化压缩可以把索引内存压到 100MB 以内——这时候差距就实实在在了。
核心规律:向量数据库的性能瓶颈跟你存了多少文档没关系,跟你有多少个 chunks(以及每个 chunk 的维度)有关。文章数和 chunk 数的比例取决于你的分块策略——我自己的策略是 500 字一个 chunk,重叠 50 字,所以一篇文章平均产生 24 个 chunks。如果你用更激进的分块策略(比如 200 字一个 chunk),chunk 数会翻倍。

Chroma vs Qdrant 全维度对比:部署、性能、规模、维护、成本
这个问题得单开一节说,因为它跟技术选型是两码事,很多人混在一起想。
Notion AI、语雀 AI、飞书智能伙伴——这些方案的核心卖点是一致的:你把内容放进去,他们帮你搞定检索和问答,你不用管向量数据库是什么。
好处就不展开了,说说不好的部分。
数据出境。Notion AI 的数据处理在美国,企业用户注意合规。
分块策略不可控。专有方案的分块粒度、重叠窗口、embedding 模型——全部黑盒。你不知道 500 字一个 chunk 还是 1000 字一个 chunk,你不知道用的什么 embedding 模型,你更不知道检索时用的 top-k 是多少。这对非技术人员无所谓,但如果你是一个在纠结 Chroma 和 Qdrant 的人——你大概率是想要控制的。
锁定效应。你的知识库越做越大,迁移成本就越来越高。三年前我同时用 Notion 和飞书记笔记,后来想把两边的数据合并到一个自建知识库里——API 导出来的格式五花八门,光数据清洗花了一整天。
月费不低。Notion AI 按月收费,语雀高级版也是订阅制。一个月的费用够你买一台轻量云服务器跑 Qdrant 了。
所以我的判断很直接:专有方案适合"我只需要一个能搜自己笔记的工具"的人。如果你已经在读这篇文章了,你大概率不是这个人群。
“💬 你的知识库用的是哪种方案?
评论区说说,码哥猜选 D 的人最多 😂
好,前面铺垫完了。现在给你一套可以直接拿来用的决策框架。
直接上 ChromaDB。别犹豫。
这个阶段最重要的事情不是"选对技术",是把知识库真正跑起来、用起来。Chroma 的零部署成本意味着你不会在"配环境"这个环节消耗心力——你只需要专注于整理内容、调分块策略、优化检索 prompt。这些才是决定知识库质量的核心变量,不是向量数据库选型。
我见过太多这样的案例:有人花了一周搭 Qdrant + Ollama + Dify 全家桶,知识库没往里塞几篇文章。而另一个人用 Chroma + 命令行脚本,两周内塞了 300 篇文章,每天用起来。
ChromaDB 继续。加 SSD,调 HNSW 参数。
到这个阶段你会感觉到性能变化,但不是断崖式的。Chroma 支持调 HNSW 的两个关键参数:
hnsw:space:距离函数,余弦相似度(cosine)对文本语义检索效果最好hnsw:construction_ef:构建时搜索宽度,默认 100,调到 200 能提升召回率但构建变慢hnsw:search_ef:查询时搜索宽度,默认 10,调到 50-100 能显著提升召回率如果检索速度开始变慢,优先把数据放到 SSD 上。向量检索是随机读为主,HDD 到 SSD 的提升比任何参数调优都明显。
该上 Qdrant 了。
两个硬指标到这个量级会变成真问题:
Qdrant,没商量。
Chroma 的嵌入式模型意味着每个 Python 进程跑自己的实例。如果两个人用的不是同一台机器,他们查的是两个不同的 Chroma 数据库。解决方案两个:要么共享文件系统 + 锁(复杂度爆炸),要么上 Qdrant(一个独立服务,所有客户端都连它)。

向量数据库选型决策流程:根据文章数量、团队规模、延迟要求逐步判断
这节是本文最值钱的部分——不只告诉你什么时候该考虑迁移,还告诉你什么时候不需要。
很多人犯的错误是:向量数量到了一个整数关口(比如 10000 条),就觉得"该迁移了"。错。迁移的信号是体验变差,不是数字变大。
我总结了三个信号,触发两个就该动:
这是最直观的指标。我用 Chroma 跑 5877 个 chunks 的时候,P99 延迟在 0.8 秒。按 Chroma 在全内存索引模式下的性能曲线推算,这个延迟在 5 万 chunks 以内大概在 1 秒出头,10 万 chunks 时会开始逼近 2 秒。
怎么测?在你的检索函数前后加个计时:
import time
start = time.time()
results = collection.query(query_texts=["你的测试查询"], n_results=5)
elapsed = time.time() - start
print(f"查询耗时: {elapsed:.2f}s")
多跑几次取 P99,不要只看平均值——偶尔一次网络抖动把延迟拉到 5 秒,不代表向量数据库有问题。
Chroma 把索引全放内存里。如果你的机器总共 8GB RAM,Chroma 占了 4GB,剩下的给操作系统、浏览器、IDE——随时可能触发 swap,那时候延迟就不是 2 秒,是 20 秒。
检查方法:
ps aux | grep chroma # 找到进程 PID
top -pid <PID> # 看 RES 列,单位是 KB
这个信号最容易被忽略。Chroma 的默认后端是 SQLite,写入是文件级锁。如果某个同事在往知识库里加新文章,其他人可能要等写入完成才能查询。在单人场景下这不是问题,两个人偶尔踩到锁的概率也不高——但 5 个人以上,几乎一定会撞。
三信号决策口诀:触发两个 → 考虑迁移。只触发一个 → 先优化配置(调 HNSW 参数 / 换 SSD / 加内存)。
另外提一嘴:Chroma 1.5 新增了 Rust 客户端支持,如果你对性能敏感,可以试试把查询部分的代码用 Rust 重写,Python 通过 PyO3 调用——但这属于"在 Chroma 的框架里优化",不是"换 Qdrant"。两者成本差了不止一个数量级。
到此为止,我得把自己的牌亮出来,不然这篇文章就变成"假装客观"了。
我现在的配置:240 篇文章,5877 个 chunks,embedding 模型 paraphrase-multilingual-MiniLM-L12-v2(384 维),全部跑在 ChromaDB 上。
为什么没选 Qdrant? 不是因为它不好,是因为我根本没碰到它的适用场景。查询延迟 < 1 秒,内存 < 200MB,只有我自己在用——三个迁移信号一个都没触发。我的注意力应该放在写更好的内容、调更准的检索 prompt 上,而不是维护一个独立服务。
未来会换吗? 如果我一年内从 240 篇涨到 500 篇(~15000 chunks),Chroma 仍然扛得住。如果知识星球成员开始共享检索(多人并发),我也不会换 Qdrant——我会让每人本地跑自己的 Chroma 实例。内容同步问题用 Git 解决就行,比维护一个中心化向量数据库简单得多。
什么时候我会真的迁移? 两种场景:
但目前,这两种场景都不存在。所以我的选择是:把时间花在内容上,而不是基础设施上。
Q:Chroma 能处理多少向量?有硬上限吗?
A:没有硬编码的上限。Chroma 的 HNSW 实现基于 hnswlib,理论上支持百万级向量。但实际瓶颈在内存——索引全在内存里,向量越多内存越大。我的建议是 10 万 chunks 以内放心用,10-30 万之间需要监控内存,超过 30 万开始考虑 Qdrant 或其他支持磁盘索引的方案。
Q:如果我先用 Chroma,将来迁移到 Qdrant 会不会很麻烦?
A:迁移本身不复杂——向量数据和元数据都是标准格式,写一个导出脚本把 Chroma 的数据 dump 出来,再批量 upsert 到 Qdrant 就行。真正麻烦的是你的代码要改:Chroma 和 Qdrant 的 API 不一样,查询参数的语义也不完全等价。建议在你的检索逻辑外面包一层抽象接口,将来换引擎只改实现不改调用方。
Q:Qdrant 的量化压缩会损失检索精度吗?
A:会。Scalar Quantization(float32 → uint8)的精度损失通常在 1-3% 的召回率范围内,大多数场景下感知不到。Product Quantization 压缩率更高但精度损失也更大。建议先用 SQ,召回率下降超过 5% 再考虑回退到全精度。
Q:有没有介于 Chroma 和 Qdrant 之间的方案?
A:LanceDB 是一个有意思的中位数——它也是嵌入式引擎,但基于 Lance 列式存储格式,支持磁盘索引,不需要全放内存。缺点是社区比 Chroma 小,文档不如 Chroma 完善。如果你真的很纠结,可以去看看,但我不建议在"中位数方案"上花太多时间——这条路的尽头通常是两个都试了,然后选了其中一个。
Q:要不要考虑 Milvus?
A:Milvus 是好东西,但它的设计目标是"云原生、分布式、十亿级向量"。大部分自建知识库的场景不需要它——就像你不会为了送外卖买一辆重卡。不过如果你已经在大厂内部用 Milvus 做业务、顺便用它搭知识库,那没问题——有现成的基础设施就别折腾了。如果你从零开始选,Milvus 的维护成本是 Qdrant 的 3 倍,是 Chroma 的 10 倍。
折腾了一圈,回到原点。结论其实很简单:向量数据库选型的关键变量不是功能对比表,是你的阶段。 起步期纠结 Chroma 和 Qdrant 的区别,跟刚开始跑步就纠结买 Nike 还是 Asics 一样——穿起来跑才是正经事。
我自己走了一条弯路的经验是:一开始装了 Qdrant,因为大家都说它是"生产级"。但我的"生产"只有我一个人在用,Qdrant 的优点我一个都没享受到,缺点一个都没躲过。后来退回 Chroma,世界清净了。
如果你也处在"刚开始倒腾自建知识库"这个阶段,我的建议只有一句话:pip install chromadb,然后把时间花在塞内容和调 prompt 上。等你真的感觉查询慢了、内存不够了、团队开始抱怨了——那才是你该研究 Qdrant 的时候。到那一天你来看这篇文章的「三个迁移信号」那节,照着判断就行。
下一篇打算拆一下不同 embedding 模型对中文语义检索的实际效果,用我自己的知识库跑一遍 benchmark。