Qdrant vs Milvus 向量数据库对比选型指南
在 AI 应用中,向量数据库承担着海量 Embedding 数据的存储与相似性检索职责。Qdrant 和 Milvus 是目前最流行的两个开源向量数据库,本文从多个维度进行深度对比,帮助你选型决策。
一、概览对比
| 维度 | Qdrant | Milvus |
|---|---|---|
| 开源协议 | Apache 2.0 | Apache 2.0 |
| 首次发布 | 2021年 | 2020年 |
| 开发语言 | Rust | Go + C++ |
| GitHub Star | ~28k | ~28k |
| 社区活跃度 | 增长快 | 成熟稳定 |
| 文档完善度 | 较完善 | 非常完善 |
二、核心架构对比
2.1 Qdrant 架构
┌─────────────────────────────────────────────┐
│ Qdrant │
├─────────────────────────────────────────────┤
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Node 1 │ │ Node 2 │ │ Node 3 │ │
│ │ (Rust) │ │ (Rust) │ │ (Rust) │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │
│ └────────────┼────────────┘ │
│ │ │
│ ┌──────────┴──────────┐ │
│ │ Consensus Layer │ │
│ │ (Raft 协议) │ │
│ └─────────────────────┘ │
└─────────────────────────────────────────────┘
- 单进程架构:所有功能运行在一个 Rust 进程中
-
- 无外部依赖:不需要 Zookeeper、Etcd 等协调服务
-
- 轻量级:二进制文件 ~50MB,内存占用低
-
- Raft 共识:内置分布式协调,配置简单
2.2 Milvus 架构
┌──────────────────────────────────────────────────┐
│ Milvus │
├──────────────────────────────────────────────────┤
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ Proxy 层 │ │ Proxy 层 │ │ Proxy 层 │ │
│ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ │
│ │ │ │ │
│ ┌─────┴───────────────┴───────────────┴─────┐ │
│ │ Message Queue (Kafka/Pulsar) │ │
│ └─────────────────────┬───────────────────────┘ │
│ │ │
│ ┌──────────────┴──────────────┐ │
│ │ Root Coord + Data Coord │ │
│ │ + Query Coord │ │
│ └──────────────┬───────────────┘ │
│ │ │
│ ┌──────────────┼───────────────┐ │
│ │ │ │ │
│ ┌────┴────┐ ┌─────┴────┐ ┌─────┴─────┐ │
│ │Data Node│ │Query Node│ │Index Node │ │
│ └─────────┘ └──────────┘ └───────────┘ │
└──────────────────────────────────────────────────┘
- 分布式架构:Proxy、Storage、Compute 分离
-
- 依赖外部服务:需要 Zookeeper、Etcd、Kafka/Pulsar
-
- 组件多:Root Coord、Data Coord、Query Coord、Index Node 等
-
- 支持多索引:HNSW、IVF、PQ、DiskANN 等
三、性能对比
3.1 检索性能
在标准 Benchmark 测试中(10M 768维向量,HNSW 索引):
| 指标 | Qdrant | Milvus |
|---|---|---|
| QPS | ~5000 | ~4000 |
| 延迟 P99 | ~50ms | ~80ms |
| 内存占用 | ~8GB | ~15GB |
| 索引构建速度 | 快 | 中等 |
注:具体数值受硬件、数据集、参数配置影响,以上为参考值
3.2 写入性能
| 指标 | Qdrant | Milvus |
|---|---|---|
| 批量写入吞吐 | 高 | 高 |
| 实时写入 | 支持 | 支持(需 Kafka) |
| 写入延迟 | 低 | 依赖队列 |
3.3 性能小结
- Qdrant:延迟更低,资源占用更少,适合中小规模
-
- Milvus:海量数据时更稳,索引类型更丰富
四、功能特性对比
4.1 索引类型
| 索引类型 | Qdrant | Milvus |
|---|---|---|
| HNSW | ✅ | ✅ |
| IVF/IVF-PQ | ✅ | ✅ |
| DiskANN | ❌ | ✅ |
| SCANN | ❌ | ✅ |
| Binary Vector | ✅ | ✅ |
| Sparse Vector | ✅ | ✅ |
| Multi-Vector | ✅ | ✅ |
4.2 过滤能力
Qdrant 强项:
python
# Qdrant 支持在检索时带结构化字段过滤
results = client.search(
collection_name="articles",
query_vector=query_embedding,
query_filter={
"must": [
{"key": "category", "match": {"value": "tech"}},
{"key": "published_year", "range": {"gte": 2023}}
]
},
limit=10
)
```
**Milvus 过滤**:
```python
# Milvus 同样支持,但语法略有不同
results = collection.search(
data=[query_embedding],
anns_field="vector",
param={"metric_type": "IP", "params": {"ef": 128}},
filter="category == 'tech' && published_year >= 2023",
limit=10
)
```
### 4.3 分片与副本
| 特性 | Qdrant | Milvus |
|------|--------|--------|
| 水平分片 | ✅ | ✅ |
| 副本机制 | ✅ | ✅ |
| 故障转移 | 自动 | 需要配置 |
| 读写分离 | ✅ | ✅ |
---
## 五、部署复杂度对比
### 5.1 Qdrant 部署
**单机模式**:
```bash
# 下载二进制,一行命令启动
curl -L https://github.com/qdrant/qdrant/releases/latest/download/qdrant-x86_64-pc-windows-msvc.zip -o qdrant.zip
unzip qdrant.zip
./qdrant
Docker 部署:
bash
docker run -p 6333:6333 \
-v $(pwd)/qdrant_storage:/qdrant/storage \
qdrant/qdrant
```
**Docker Compose 集群**(3节点):
```yaml
version: '3.8'
services:
qdrant-1:
image: qdrant/qdrant:latest
environment:
QDRANT__CLUSTER__ENABLED: "true"
QDRANT__CLUSTER__P2P__PORT: "6337"
volumes:
- ./qdrant1_storage:/qdrant/storage
- ports:
- - "6333:6333"
- - "6334:6334"
qdrant-2:
image: qdrant/qdrant:latest
environment:
QDRANT__CLUSTER__ENABLED: "true"
QDRANT__CLUSTER__P2P__PORT: "6337"
QDRANT__CLUSTER__SEED: "qdrant-1:6337"
volumes:
- ./qdrant2_storage:/qdrant/storage
qdrant-3:
image: qdrant/qdrant:latest
environment:
QDRANT__CLUSTER__ENABLED: "true"
QDRANT__CLUSTER__P2P__PORT: "6337"
QDRANT__CLUSTER__SEED: "qdrant-1:6337"
volumes:
- ./qdrant3_storage:/qdrant/storage
- ```
### 5.2 Milvus 部署
**依赖服务**:需要 MySQL(元数据)+ Zookeeper + Kafka/Pulsar
**Docker Compose 完整部署**:
```yaml
version: '3.8'
services:
etcd:
image: quay.io/coreos/etcd:v3.5.5
environment:
- ETCD_AUTO_COMPACTION_MODE=revision
- - ETCD_AUTO_COMPACTION_RETENTION=1000
- - ETCD_QUOTA_BACKEND_BYTES=4294967296
- volumes:
- - etcd_data:/etcd
- command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd
minio:
image: minio/minio:latest
environment:
MINIO_ACCESS_KEY: minioadmin
MINIO_SECRET_KEY: minioadmin
volumes:
- minio_data:/minio_data
- command: minio server /minio_data
kafka:
image: confluentinc/cp-kafka:7.5.0
depends_on:
- zookeeper
- environment:
- KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
- KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
- KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092
- KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
- KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
- KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
zookeeper:
image: confluentinc/cp-zookeeper:7.5.0
environment:
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_TICK_TIME: 2000
milvus:
image: milvusdb/milvus:v2.3.3
depends_on:
- etcd
- - kafka
- - minio
- environment:
- ETCD_ENDPOINTS: etcd:2379
- MINIO_ADDRESS: minio:9000
- KAFKA_BOOTSTRAP_SERVERS: kafka:9092
- volumes:
- - milvus_data:/var/lib/milvus
- ports:
- - "19530:19530"
- - "9091:9091"
- ```
### 5.3 部署复杂度小结
| 维度 | Qdrant | Milvus |
|------|--------|--------|
| **依赖服务** | 无 | Zookeeper + Kafka + S3 |
| **部署步骤** | 1-2步 | 10+ 步骤 |
| **配置复杂度** | 低 | 高 |
| **K8s 支持** | 原生支持 | 官方 Operator |
| **资源占用** | 轻量 | 较重 |
---
## 六、生态与工具对比
### 6.1 客户端 SDK
| 语言 | Qdrant | Milvus |
|------|--------|--------|
| Python | ✅ | ✅ |
| Go | ✅ | ✅ |
| Java | ✅ | ✅ |
| Rust | ✅ | ✅ |
| Node.js/TS | ✅ | ✅ |
| C++ | ❌ | ✅ |
| Ruby | ✅ | ✅ |
### 6.2 可视化工具
| 工具 | Qdrant | Milvus |
|------|--------|--------|
| Web UI | Qdrant Console | Attu |
| 官方 Dashboard | ✅ | ✅ (Attu) |
| 第三方工具 | 较少 | 较多 |
### 6.3 云服务
| 厂商 | Qdrant | Milvus |
|------|--------|--------|
| 官方云 | Qdrant Cloud | Zilliz Cloud |
| AWS | 合作 | 原生支持 |
| Azure | 待定 | 原生支持 |
| GCP | 待定 | 原生支持 |
---
## 七、使用场景选型
### 7.1 推荐 Qdrant 的场景
✅ 中小规模向量数据(百万~千万级)
✅ 快速原型开发,需要快速部署
✅ 强过滤查询需求(向量+标量联合检索)
✅ 资源受限环境(边缘设备、小型服务器)
✅ 实时性要求高(低延迟检索)
✅ 团队规模小,运维能力有限
**典型案例**:
- RAG 应用中的向量检索
- - 推荐系统(用户/物品向量)
- - 图片相似度搜索
- - 语义搜索服务
### 7.2 推荐 Milvus 的场景
✅ 超大规模向量数据(亿级以上)
✅ 需要丰富的索引类型(DiskANN、SCANN)
✅ 已有大数据团队和复杂运维体系
✅ 需要成熟的生态和周边工具
✅ 多租户场景(Milvus 隔离性更好)
✅ 需要 TCSD/PCA 等高级索引
**典型案例**:
- 搜索引擎核心检索
- - 亿级人脸/图片检索
- - DNA 序列比对
- - 化学分子相似度搜索
---
## 八、实战代码对比
### 8.1 Python 客户端初始化
**Qdrant**:
```python
from qdrant_client import QdrantClient
client = QdrantClient(host="localhost", port=6333)
# 或使用远程服务
client = QdrantClient(
url="https://xxx.cloud.qdrant.io",
api_key="your-api-key"
)
```
**Milvus**:
```python
from pymilvus import connections, Collection
connections.connect(host="localhost", port=19530)
8.2 创建 Collection
Qdrant:
python
from qdrant_client.models import Distance, VectorParams, HnswConfig
client.create_collection(
collection_name="articles",
vectors_config=VectorParams(
size=768,
distance=Distance.COSINE,
hnsw_config=HnswConfig(m=16, ef_construct=128)
)
)
```
**Milvus**:
```python
from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType
fields = [
FieldSchema(name="id", dtype=DataType.INT64, is_primary=True),
FieldSchema(name="vector", dtype=DataType.FLOAT_VECTOR, dim=768)
]
schema = CollectionSchema(fields=fields, description="Articles collection")
collection = Collection(name="articles", schema=schema)
index_params = {
"index_type": "HNSW",
"params": {"M": 16, "efConstruction": 128},
"metric_type": "COSINE"
}
collection.create_index(field_name="vector", index_params=index_params)
```
### 8.3 插入和检索
**Qdrant**:
```python
import uuid
# 插入
client.upsert(
collection_name="articles",
points=[
{
"id": str(uuid.uuid4()),
"vector": [0.1] * 768,
"payload": {"title": "Hello World", "category": "tech"}
}
]
)
# 检索
results = client.search(
collection_name="articles",
query_vector=[0.1] * 768,
query_filter={
"must": [
{"key": "category", "match": {"value": "tech"}}
]
},
limit=5
)
```
**Milvus**:
```python
# 插入
import random
data = [[random.random() for _ in range(768)] for _ in range(10)]
collection.insert([data])
# 检索
search_params = {"metric_type": "COSINE", "params": {"ef": 128}}
results = collection.search(
data=[[random.random() for _ in range(768)]],
anns_field="vector",
param=search_params,
limit=5,
output_fields=["title"]
)
```
---
## 九、总结对比
| 评估维度 | Qdrant | Milvus |
|----------|--------|--------|
| **上手难度** | ⭐⭐ 简单 | ⭐⭐⭐⭐ 较复杂 |
| **部署成本** | ⭐⭐ 低 | ⭐⭐⭐⭐ 高 |
| **检索性能** | ⭐⭐⭐⭐ 高 | ⭐⭐⭐ 中高 |
| **扩展能力** | ⭐⭐⭐ 中 | ⭐⭐⭐⭐⭐ 强 |
| **运维友好** | ⭐⭐⭐⭐⭐ 友好 | ⭐⭐ 一般 |
| **生态成熟度** | ⭐⭐⭐ 成长中 | ⭐⭐⭐⭐⭐ 成熟 |
| **社区支持** | ⭐⭐⭐ 活跃 | ⭐⭐⭐⭐ 庞大 |
### 最终选型建议
┌─────────────────────────────────────────────────────────┐