如果你已经有 PostgreSQL,而且向量只是业务数据的一部分,先用 pgvector;如果想把向量检索单独拆成一个服务,Qdrant 更顺手;只有当单机确实放不下、团队也准备好维护更多组件时,再考虑 Milvus Distributed。
这比“哪个跑分最高”更重要。向量数据库最后吃掉的不是一个软件名,而是内存、磁盘、索引构建时间和你的运维精力。
| 方案 | 更适合的项目 | 运维复杂度 | VPS 起步建议 | 主要代价 |
|---|---|---|---|---|
| pgvector | 已经使用 PostgreSQL,需要事务、JOIN 和向量检索 | 低 | 2核4G 做验证,生产更建议 4核8G 起 | 向量索引会和业务表争内存、I/O |
| Qdrant | RAG、语义搜索,需要独立 API 和 payload 过滤 | 中 | 2核4G 做小规模验证,4核8G 更适合正式使用 | 多维护一个服务,必须单独备份和鉴权 |
| Milvus Standalone | 数据和查询压力明显增长,又暂时不想上集群 | 中高 | 官方最低 8GB,建议 16GB 内存 | 组件和资源占用高于轻量方案 |
| Milvus Distributed | 单机容量或吞吐已经成为明确瓶颈 | 高 | 不建议塞进一台便宜 VPS | 需要多节点、对象存储和更成熟的监控运维 |
如果只是给 Dify、AnythingLLM 或自己的 RAG 应用配一个向量库,我会优先在 pgvector 和 Qdrant 之间选。Milvus 没问题,但“以后可能会很大”不是现在就上分布式系统的充分理由。
站内已经有完整的 Dify 私有 RAG 部署教程 和 AnythingLLM 私有知识库教程。这篇只解决它们下面那层:向量到底怎么存、机器怎么买、服务怎么安全地跑起来。
“100 万条向量需要多大内存”没有脱离模型的统一答案。至少要先知道:
- 向量有多少维;
- 使用 float32、half precision 还是量化数据;
- 用精确搜索、HNSW 还是 IVFFlat;
- 每条记录还带多少文本、标签和业务 payload;
- 是否有副本、WAL、快照和并发查询;
- 索引构建期间需要多少工作内存。
以 float32 原始向量为例,先做一个最低限度的估算:
原始向量字节数 ≈ 向量数量 × 维度 × 4
pgvector 的官方 README 写得更精确:vector 每条占用 4 × dimensions + 8 字节。假设是 1536 维:
10 万条:100000 × (4 × 1536 + 8) ≈ 587 MiB
100 万条:1000000 × (4 × 1536 + 8) ≈ 5.73 GiB
这还只是向量本身,不包含 PostgreSQL 行开销、HNSW 图、payload、索引构建内存、缓存和操作系统。看到这里就能明白:4GB VPS 可以做功能验证,却不能因为“原始向量才几 GB”就直接承诺能稳定装下 100 万条 1536 维 HNSW 数据。
如果模型输出 768 维,原始数据大约减半;换成 half precision 也能缩小工作集,但会带来精度和实现上的取舍。先用自己的 embedding 维度算原始量,再为索引、业务字段、备份和增长留余量,比照搬别人的“容量表”靠谱。
pgvector 是 PostgreSQL 扩展。它的优势不是“永远最快”,而是你可以把向量和用户、文档、权限、订单等关系数据放在同一套事务和备份体系里。
当前官方 README 支持精确近邻搜索,也支持 HNSW 和 IVFFlat 两种近似索引。HNSW 的速度与召回折中通常更好,但构建更慢、占用更多内存;IVFFlat 构建更轻,参数和数据分布却更影响召回。
比较适合 pgvector 的情况:
- 已经有稳定的 PostgreSQL;
- 向量检索要和大量关系条件一起过滤;
- 数据规模暂时不大,团队不想多维护一个数据库;
- 需要 PostgreSQL 的事务、JOIN、WAL、PITR 和现有监控工具。
它的坑也很直接:业务查询、自动清理、备份和 HNSW 建索引都在抢同一台数据库的资源。官方文档还提醒,HNSW 图能放进 maintenance_work_mem 时构建更快,但这个值开得过大又可能把服务器内存吃光。
小团队已经有 PostgreSQL 时,pgvector 往往是成本最低的第一步;等向量检索真的形成独立负载,再拆到 Qdrant,也比一开始就维护三四套组件轻松。
Qdrant 提供独立的 REST 和 gRPC 接口,向量、payload 和过滤都围绕检索场景设计。对 RAG 知识库来说,它比“在业务数据库里再塞一个扩展”边界更清楚:应用坏了不一定拖垮向量库,向量库扩容也不用先动主业务数据库。
Qdrant 适合这些情况:
- 多个应用共用一个向量服务;
- payload 过滤是检索链路的一部分;
- 希望用独立 API 管理 collection、point 和 snapshot;
- 后面可能单独升级内存、磁盘或拆分节点。
代价是你要自己处理 API Key、TLS、快照、升级和监控。Qdrant 自托管版本不是装完就自动安全,6333 端口也不应该直接暴露到公网。
Milvus 有 Lite、Standalone 和 Distributed 等部署方式。Standalone 可以在单机运行;Distributed 面向超过单机容量的大规模场景,组件和运维复杂度都会明显增加。
Milvus 当前官方硬件建议里,Standalone 最低 8GB、建议 16GB 内存;Cluster 最低 32GB、建议 128GB,而且磁盘至少应为 SATA SSD,推荐 NVMe。这个数字已经说明,Milvus 不是 2核4G 小鸡上的同级替代品。
什么时候值得考虑它?
- 单机资源已经通过监控确认是瓶颈;
- 数据规模、写入和查询量持续增长;
- 团队能维护对象存储、监控、备份和多组件升级;
- 分布式带来的收益大于额外机器和人工成本。
如果项目刚开始,只是担心“将来有 1 亿条”,先把数据增长、查询并发和延迟目标记录下来。没有这些数据,分布式只是提前交运维税。
下面是保守的起步档位,不是容量保证。不同维度、索引参数、payload、并发和 CPU 平台会把结果拉得很开。
适合已有 PostgreSQL 的 pgvector 验证,或者低并发 Qdrant 测试。系统、Docker 和监控本身也要占内存,别把 4GB 全算给索引。
这档不适合 Milvus Standalone,也不适合大批量构建高维 HNSW。内存接近上限时,Swap 只能避免进程立刻退出,不能让检索保持稳定延迟。
如果要跑一个独立 Qdrant、定期快照,再留出系统和反向代理资源,8GB 会比 4GB 从容很多。已有 PostgreSQL + pgvector 的项目,也能给 shared buffers、查询和索引维护留出空间。
但 8GB 仍然不是“百万向量通行证”。前面算过,100 万条 1536 维 float32 的原始向量就接近 5.73GiB,索引和业务数据还没算进去。
到了 16GB,可以认真测试更大的 Qdrant collection、pgvector HNSW,或者按 Milvus 官方建议部署 Standalone。是否继续单机,要看故障恢复目标:数据库和索引都只在一台机器上,升级、磁盘故障和误删仍然会一起影响服务。
如果你还在 1核1G、2核2G 和 2核4G 之间犹豫,先看这篇 VPS 配置选择指南,把系统、应用和数据库的基础开销一起算进去。
别拿一个空 collection 跑通查询,就宣布机器够用了。真正容易把内存和磁盘顶满的是批量导入、索引构建、过滤查询和快照同时发生。
准备一批能代表真实业务的数据,向量维度、文本长度、标签数量和过滤条件都不要随便简化。先记录没有索引时的数据目录大小和进程内存,再创建准备上线的 HNSW 或 IVFFlat 索引,比较索引前后的磁盘、内存峰值和构建时间。
接着回放真实查询:既要有普通近邻搜索,也要包含业务会用到的租户、权限、时间和分类过滤。只测单请求平均延迟意义不大,至少同时观察高峰并发、P95/P99 延迟、错误率和召回变化。
最后做一次故障演练:创建快照,把副本传到另一处,删除测试 collection,再按文档恢复。恢复时间如果已经超过业务能接受的停机窗口,就算日常查询很快,这套配置也不能算通过。
把每轮的向量数量、维度、索引参数、磁盘占用、内存峰值和查询结果记下来。数据翻倍时重复一次,比照搬别人的跑分更能判断下一步该加内存、换磁盘还是拆成独立服务。
向量检索常见的购买优先级是:
- 内存余量:索引构建和查询都需要工作集,长期贴着 95% 内存运行很危险。
- SSD/NVMe 随机 I/O:数据、WAL、快照和索引都会读写磁盘;只看容量不看延迟容易踩坑。
- CPU 型号:建索引和距离计算吃 CPU,老款共享多核不一定比新平台少核快。
- 备份出口:快照要传到另一台机器或对象存储,出站流量和速度都会影响恢复时间。
- 机房位置:向量库尽量靠近调用它的应用,不要让每次检索跨洲绕路。
月成本也别只算 VPS:
真实月成本 = VPS + 异地备份/对象存储 + 快照空间 + 出站流量 + 维护时间
pgvector 可能省下一套服务,却把风险集中到主数据库;Qdrant 多一个容器,但边界清楚;Milvus Distributed 能横向扩展,也会把机器数量和运维成本一起抬高。
下面以 Ubuntu/Debian、已经安装 Docker Compose、宿主机安装 Caddy 为前提。示例固定到 2026 年 7 月 17 日发布的 Qdrant v1.18.3,不要在生产环境长期使用 latest。
创建目录:
sudo mkdir -p /opt/qdrant/{storage,snapshots}
sudo chown -R "$USER":"$USER" /opt/qdrant
cd /opt/qdrant
生成 API Key,并把 .env 权限收紧:
umask 077
printf 'QDRANT_API_KEY=%s\n' "$(openssl rand -hex 32)" > .env
创建 compose.yaml:
services:
qdrant:
image: qdrant/qdrant:v1.18.3
container_name: qdrant
restart: unless-stopped
ports:
- "127.0.0.1:6333:6333"
environment:
QDRANT__SERVICE__API_KEY: "${QDRANT_API_KEY}"
volumes:
- ./storage:/qdrant/storage
- ./snapshots:/qdrant/snapshots
这里故意把 6333 绑定到 127.0.0.1。外部不能直接访问它,只能经过宿主机上的 Caddy。没有使用 gRPC 的话,不必把 6334 暴露出来。
启动并检查:
docker compose pull
docker compose up -d
docker compose ps
set -a
. ./.env
set +a
curl -fsS -H "api-key: ${QDRANT_API_KEY}" http://127.0.0.1:6333/collections
能返回 collection 列表,说明容器和鉴权都在工作。若返回 401,先确认 .env 已加载、容器环境变量存在,并检查 docker compose logs qdrant。
先把 vector.example.com 的 A/AAAA 记录指向 VPS,并确保防火墙只开放 SSH、80 和 443。6333/tcp 不需要公网放行。
宿主机 Caddyfile:
vector.example.com {
reverse_proxy 127.0.0.1:6333
}
检查并加载:
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
Caddy 会为有效域名申请和续期证书。客户端访问时仍要带 Qdrant 的 api-key 请求头:
curl -fsS \
-H "api-key: ${QDRANT_API_KEY}" \
https://vector.example.com/collections
请把 vector.example.com 替换成自己的域名。API Key 不要写进 Caddyfile、Git 仓库或前端 JavaScript;它应该保存在服务端环境变量或密钥管理系统里。
假设 collection 名叫 docs,创建快照:
curl -fsS -X POST \
-H "api-key: ${QDRANT_API_KEY}" \
http://127.0.0.1:6333/collections/docs/snapshots
列出已有快照:
curl -fsS \
-H "api-key: ${QDRANT_API_KEY}" \
http://127.0.0.1:6333/collections/docs/snapshots
快照文件仍在宿主机的 /opt/qdrant/snapshots 目录里。机器磁盘坏掉时,同盘快照也可能一起丢,所以要定时复制到对象存储或另一家云厂商。
恢复前先阅读与当前版本对应的 Qdrant Snapshot 文档,并在测试 collection 验证。上传本地快照的 API 形式如下:
curl -fsS -X POST \
-H "api-key: ${QDRANT_API_KEY}" \
-F "snapshot=@/path/to/docs.snapshot" \
"http://127.0.0.1:6333/collections/docs/snapshots/upload?priority=snapshot"
/path/to/docs.snapshot 是你从异地备份取回的真实文件路径。恢复会影响目标 collection,别第一次就在生产库上试。
快照、镜像和整机备份不是一回事,可以对照 VPS 快照、备份、镜像的区别 设计恢复流程。
生产升级至少做这几步:
- 阅读目标版本 release notes 和兼容说明;
- 创建 collection 快照并复制到异地;
- 记录当前镜像版本和 compose 文件;
- 把镜像 tag 改成明确版本后再拉取;
- 启动后检查健康、collection 数量和业务查询;
- 保留可回滚的旧配置和备份。
docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail=100 qdrant
数据库升级和普通 Web 容器不同。数据格式、索引重建和恢复时间都要提前验证,不能只看到容器是 running 就认为升级成功。
先连续观察业务高峰,而不是只看一次 top:
# 容器 CPU、内存和网络
docker stats qdrant
# 磁盘空间和 inode
df -h /opt/qdrant
df -i /opt/qdrant
# Qdrant 日志
docker compose logs --since=1h qdrant
# 本地健康检查
curl -fsS http://127.0.0.1:6333/healthz
# Prometheus 格式指标,需要 API Key 时保留请求头
curl -fsS -H "api-key: ${QDRANT_API_KEY}" http://127.0.0.1:6333/metrics
这些信号说明该扩容或拆分:
- 常态内存接近上限,开始持续换页或出现 OOM;
- 索引构建时业务查询明显超时;
- 磁盘剩余空间不足以同时放数据、WAL 和快照;
- 随机 I/O 延迟持续升高;
- 备份窗口越来越长,恢复演练无法在目标时间内完成;
- 单机纵向升级价格已经接近多节点或托管方案。
不要只看向量条数。用真实 embedding、真实过滤条件和并发量做压测,记录 P95/P99 延迟、召回变化、内存峰值和索引构建时间,再决定加内存、换 NVMe、做量化还是拆服务。
能做学习、功能验证和低并发小项目,默认前提是单节点、低并发、真实数据已经压测,但没有固定的向量数量保证。1536 维 float32 数据增长很快,HNSW、payload 和快照还会继续占空间。正式使用前必须用自己的数据压测。
已有 PostgreSQL、需要事务和 JOIN,先选 pgvector;希望向量检索成为独立服务,或多个应用共用,选 Qdrant。两者不是简单的性能胜负,而是系统边界不同。
当单机瓶颈已经被监控和压测证实,数据与并发确实需要分布式扩展,而且团队能维护更多组件时。只是做一个内部知识库,Milvus Distributed 往往太重。
不建议。优先让服务走同一私网、Docker 网络、VPN 或带 TLS 和鉴权的反向代理。安全组只允许可信来源,API Key 也要定期轮换。
不能。同盘快照会和原机一起承受磁盘故障、误删和账号风险。至少保留一份不同故障域的副本,并定期做恢复演练。
项目已经在 PostgreSQL 里,向量规模还小,就从 pgvector 开始;想给多个 RAG 应用提供一个独立接口,4核8G 的 Qdrant 是更容易管理的起点;确定需要单机更大资源,可以评估 8核16G+ 和 Milvus Standalone;只有单机瓶颈被证实后,再谈 Milvus Distributed。
买 VPS 时别为了省一点月费把内存压得太死。向量库最怕的不是平均负载,而是建索引、批量导入、快照和业务查询撞在一起。留出余量、把 6333 收回本机、把快照复制出去,比追一张脱离数据集的跑分表更有用。
