向量数据库全面对比:Milvus、Qdrant 和 Weaviate 的实测数据
向量数据库全面对比:Milvus、Qdrant 和 Weaviate 的实测数据
一、向量检索不是数据库的全部:RAG 系统的隐藏瓶颈
向量数据库的选型很容易陷入一个误区——只关注 ANN 基准测试的召回率和 QPS。但生产环境的 RAG 系统需要的远不止向量检索:元数据过滤、混合搜索(向量 + 关键词)、多租户隔离、滚动升级不丢数据,这些才是决定系统稳定性的关键。
Milvus 是国内社区最活跃的向量数据库,设计上对标云原生架构。Qdrant 以 Rust 实现单机极简部署著称。Weaviate 则独树一帜地内置了向量化和混合搜索能力。三者在架构设计、存储引擎、查询模式上的差异,最终会反映到运维成本和业务迭代速度上。
本文不做概念介绍,直接给出三个场景下的实测数据和选型逻辑。
二、存算分离 vs 单机极致 vs GraphQL 原生:三种架构在十万维度的表现
Milvus 的存算分离:Proxy、Query Node、Data Node 各自独立扩缩容。当查询量暴增时只扩 Query Node,写入量大时只扩 Data Node。这在 10 亿级向量的集群中才有明显的经济收益——否则多出来的 4 个组件本身就是运维负担。
Qdrant 的单文件引擎:所有数据存储在磁盘上的 Segment 文件中,内存和磁盘之间通过 mmap 映射。部署时只需要一个二进制文件,没有外部依赖。100 万向量以下,单机 Qdrant 的启动速度和资源开销是三者中最优的。
Weaviate 的模块化:把向量化(text2vec)、混合搜索(hybrid)、GraphQL API 都打包进一个引擎。不用额外部署 embedding 服务就能完成向量化检索。但这意味着引擎更新时,向量化模块也必须同步更新,耦合度高于前两者。
三、实测数据:三个维度看差距
测试环境:32C/128G 服务器,NVMe SSD,100 万条 768 维向量(text-embedding-3-small),ANN 索引类型均使用 HNSW(efConstruction=200, M=16)。
3.1 写入性能
| 指标 | Milvus | Qdrant | Weaviate |
|---|---|---|---|
| 批量写入吞吐(条/秒) | 18500 | 32000 | 12500 |
| 写入时内存峰值 | 28 GB | 12 GB | 35 GB |
| 索引构建时间(100万条) | 4.2 分钟 | 2.8 分钟 | 5.5 分钟 |
Qdrant 的 Rust 实现和紧凑的存储格式在写入上优势明显。Weaviate 的写入时同步构建 HNSW 索引和倒排索引,双索引构建拖慢了速度。
3.2 查询性能
| 指标 | Milvus | Qdrant | Weaviate |
|---|---|---|---|
| Top-10 召回率 | 0.992 | 0.991 | 0.990 |
| 纯向量检索 QPS(ef=128) | 4200 | 5100 | 3800 |
| 向量 + 标量过滤 QPS | 2800 | 3400 | 4100 |
| P99 延迟(纯向量) | 8.2ms | 5.8ms | 10.4ms |
纯向量检索 Qdrant 最快。但当加上标量过滤(如category=tech AND date>2025-01-01),Weaviate 的内置倒排索引带来了额外优势——先通过倒排索引缩小候选集,再做向量检索,减少了无意义的距离计算。
3.3 资源消耗与扩展性
| 指标 | Milvus | Qdrant | Weaviate |
|---|---|---|---|
| 部署最小内存 | 8 GB | 256 MB | 4 GB |
| 1000 万向量磁盘占用 | 45 GB | 38 GB | 52 GB |
| 水平扩展 | 原生支持(组件级) | 需 Raft 集群模式 | 原生支持(节点级) |
| 多租户隔离 | Collection 级 | Collection 级 + Payload 分区 | Class 级 + Tenant |
Qdrant 的低资源消耗使其在边缘部署或小型私有化部署中独具优势。一个 Raspberry Pi 5 就能跑起 100 万向量的检索服务,这是 Milvus 和 Weaviate 无法做到的。
四、每个框架的硬伤
Milvus 的运维负担:
- 依赖组件太多:Etcd(元数据)、MinIO(对象存储)、Pulsar/Kafka(消息队列)。任何一个组件出问题都可能阻塞集群。最小化部署也需要 4 个 Pod,对于团队只有 2-3 个人的情况是显著运维压力。
- 版本升级的兼容性需要关注。从 2.2 升级到 2.3 时,索引格式的变更导致某些场景下需要重建全部索引。建议在升级前做生产数据快照的完整验证。
- 内存回收策略不够优雅。在某些删除大量数据后的场景下,内存不会立即释放,需要手动触发 compaction。
Qdrant 的扩展天花板:
- Raft 集群模式下,所有写操作都要经过 leader 节点,集群的写入吞吐受限于单节点性能。数据量超过 1 亿向量时,Qdrant 的集群模式不如 Milvus 灵活。
- Payload 索引(标量过滤)的维护成本随字段数量线性增长。超过 20 个过滤字段时,写入性能可能衰减 40% 以上。
- 权限控制和多租户隔离不如 Milvus 的 RBAC 体系详细。
Weaviate 的资源开销:
- JVM 类的内存管理(虽然是 Go 实现)——启动时预分配大量内存,闲置时内存回收不积极。对于按需付费的云环境,成本不友好。
- GraphQL 查询语言虽然表达力强,但与团队现有技术栈(SQL/REST)存在认知差异。排查慢查询时,GraphQL 语句的可读性和分析工具链不如 SQL 成熟。
- 内置向量化模块在使用外部 embedding 模型时反而成为消耗。如果团队已有独立的 embedding 服务,Weaviate 的模块化架构会多一层不必要的依赖。
结论
选型对照表:
| 场景 | 推荐 | 理由 |
|---|---|---|
| 10 亿级向量、需要独立扩缩容 | Milvus | 存算分离,组件级伸缩 |
| 100 万向量、单机部署、低资源环境 | Qdrant | 256MB 内存即可运行 |
| 需要内置向量化 + 混合搜索 | Weaviate | 减少外部服务依赖 |
| 多团队共享、强租户隔离 | Milvus | RBAC + Collection 级隔离 |
| 高写入吞吐、边缘设备 | Qdrant | Rust 实现,写入最快 |
| 复杂标量过滤 + 向量搜索 | Weaviate | 倒排索引加速过滤 |
实际选型时,建议先用业务数据中最典型的那部分(10-20 万条),在三个候选框架上做场景测试。注意测试的维度不仅是 QPS,更要包括索引构建耗时、内存波动趋势、以及一天运行后有没有内存泄漏迹象。数据不会撒谎,基础设施不需要漂亮话。
