向量数据库选型:Milvus、Qdrant、Weaviate、Chroma 深度对比

为什么需要向量数据库

传统数据库基于精确匹配(SQL WHERE)或全文检索(倒排索引)。但在 AI 应用中,我们需要的是语义检索:找到"意思相近"的内容,而非"字面相同"的内容。

向量数据库的核心能力是 ANN(Approximate Nearest Neighbor)搜索:将文本、图像、音频等非结构化数据编码为高维向量,然后在向量空间中快速找到最近邻。

当前主流选择有四个:Milvus、Qdrant、Weaviate、Chroma。本文从架构、性能、功能、运维四个维度进行工程级对比。

架构概览

Milvus

  • 定位:云原生分布式向量数据库
  • 开发方:Zilliz(LF AI & Data 基金会托管)
  • 架构:存算分离,四层解耦(接入层、协调层、工作节点、存储层)
  • 存储后端:MinIO/S3(对象存储)+ etcd(元数据)+ Pulsar/Kafka(日志流)
  • 语言:Go + C++(核心索引引擎 Knowhere)
Client SDK
    |
Access Layer (Proxy)
    |
Coordinator (Root / Query / Data / Index)
    |
Worker Nodes (Query Node / Data Node / Index Node)
    |
Storage (MinIO + etcd + Pulsar)

Qdrant

  • 定位:高性能向量搜索引擎
  • 开发方:Qdrant(德国)
  • 架构:单二进制部署,Rust 实现,支持分片与副本
  • 存储后端:自研 WAL + 内存映射文件(mmap)
  • 语言:Rust

特点:从 v1.7 开始支持分布式集群(Raft 共识),但核心设计偏向中等规模场景。

Weaviate

  • 定位:AI-native 向量数据库(强调开箱即用的 AI 集成)
  • 开发方:Weaviate(荷兰)
  • 架构:模块化架构,内置向量化模块(text2vec-openai, text2vec-cohere 等)
  • 存储后端:自研 LSM + HNSW 索引
  • 语言:Go

独特之处:可以直接传入原始文本,Weaviate 自动调用配置好的 embedding 模型生成向量。

Chroma

  • 定位:AI 应用开发的嵌入式向量数据库
  • 开发方:Chroma(YC)
  • 架构:嵌入式(in-process)或 Client-Server 模式
  • 存储后端:SQLite(元数据)+ HNSW(向量索引)
  • 语言:Python + Rust(核心)

定位类似 SQLite 之于 PostgreSQL:开发简单、零运维,但不适合大规模生产。

核心能力对比

能力 Milvus Qdrant Weaviate Chroma
最大向量数 数十亿 数亿 数亿 数百万
分布式 原生支持 v1.7+ 支持 不支持
向量维度上限 32,768 65,536 无限制 无限制
标量过滤 支持(混合查询) 支持(丰富) 支持(GraphQL) 基础支持
多向量 支持 v1.10+ 支持(named vectors) 不支持
稀疏向量 支持 v1.7+ 不支持 不支持
混合检索 (dense+sparse) 支持 支持 支持(BM25模块) 不支持
内置 embedding 不支持 不支持(FastEmbed 可选) 原生支持 可选
多租户 Collection 级别 Payload 过滤 原生支持 Collection 级别
GPU 加速 支持(GPU 索引) 不支持 不支持 不支持

索引算法支持

索引类型 Milvus Qdrant Weaviate Chroma
HNSW 支持 默认 默认 默认
IVF_FLAT 支持 不支持 不支持 不支持
IVF_PQ 支持 不支持 不支持 不支持
SCANN 支持 不支持 不支持 不支持
DiskANN 支持 不支持 不支持 不支持
Product Quantization 支持 支持 支持(PQ) 不支持
Scalar Quantization 支持 支持 支持(BQ) 不支持

分析:Milvus 在索引种类上遥遥领先,适合需要精细调优索引策略的大规模场景。Qdrant 和 Weaviate 专注 HNSW + 量化优化,覆盖 90% 的使用场景。Chroma 仅支持 HNSW,足以应对开发阶段。

性能基准

以下数据基于 ANN-Benchmarks 和各厂商公开的 benchmark,使用 1M 向量、768 维度、HNSW 索引:

指标 Milvus Qdrant Weaviate Chroma
QPS (top-10, recall=0.95) ~3,000 ~4,500 ~1,800 ~500
延迟 P99 (ms) 5-15 3-10 10-30 20-50
索引构建速度 (1M) ~60s ~45s ~90s ~120s
内存占用 (1M, 768d) ~3GB ~2.5GB ~4GB ~3.5GB
磁盘占用 (1M, 768d) ~4GB ~3GB ~5GB ~4GB

说明:Qdrant 的 Rust 实现在单机性能上表现最优。Milvus 的优势在分布式场景下更明显。以上数据仅供参考,实际性能高度依赖硬件配置、索引参数和查询模式。

开发体验对比

Milvus

from pymilvus import MilvusClient

client = MilvusClient(uri="http://localhost:19530")

# 创建 collection
client.create_collection(
    collection_name="articles",
    dimension=768,
    metric_type="COSINE",
)

# 插入数据
data = [
    {"id": 1, "vector": [0.1] * 768, "title": "AI 入门", "category": "tech"},
    {"id": 2, "vector": [0.2] * 768, "title": "机器学习", "category": "tech"},
]
client.insert(collection_name="articles", data=data)

# 搜索(带标量过滤)
results = client.search(
    collection_name="articles",
    data=[[0.15] * 768],
    limit=5,
    filter='category == "tech"',
    output_fields=["title", "category"],
)

Qdrant

from qdrant_client import QdrantClient
from qdrant_client.models import VectorParams, Distance, PointStruct, Filter, FieldCondition, MatchValue

client = QdrantClient(url="http://localhost:6333")

# 创建 collection
client.create_collection(
    collection_name="articles",
    vectors_config=VectorParams(size=768, distance=Distance.COSINE),
)

# 插入数据
client.upsert(
    collection_name="articles",
    points=[
        PointStruct(id=1, vector=[0.1] * 768,
                    payload={"title": "AI 入门", "category": "tech"}),
        PointStruct(id=2, vector=[0.2] * 768,
                    payload={"title": "机器学习", "category": "tech"}),
    ],
)

# 搜索(带过滤)
results = client.query_points(
    collection_name="articles",
    query=[0.15] * 768,
    limit=5,
    query_filter=Filter(
        must=[FieldCondition(key="category", match=MatchValue(value="tech"))]
    ),
)

Weaviate

import weaviate
from weaviate.classes.config import Configure, Property, DataType

client = weaviate.connect_to_local()

# 创建 collection(内置 vectorizer)
articles = client.collections.create(
    name="Article",
    vectorizer_config=Configure.Vectorizer.text2vec_openai(),
    properties=[
        Property(name="title", data_type=DataType.TEXT),
        Property(name="category", data_type=DataType.TEXT),
    ],
)

# 插入数据(自动生成向量)
articles.data.insert({"title": "AI 入门", "category": "tech"})
articles.data.insert({"title": "机器学习", "category": "tech"})

# 语义搜索(传文本即可)
results = articles.query.near_text(
    query="人工智能基础",
    limit=5,
    filters=weaviate.classes.query.Filter.by_property("category").equal("tech"),
)

client.close()

Chroma

import chromadb

client = chromadb.PersistentClient(path="./chroma_db")

collection = client.get_or_create_collection(
    name="articles",
    metadata={"hnsw:space": "cosine"},
)

# 插入数据
collection.add(
    ids=["1", "2"],
    embeddings=[[0.1] * 768, [0.2] * 768],
    documents=["AI 入门", "机器学习"],
    metadatas=[{"category": "tech"}, {"category": "tech"}],
)

# 搜索
results = collection.query(
    query_embeddings=[[0.15] * 768],
    n_results=5,
    where={"category": "tech"},
)

部署与运维

部署复杂度

方案 Milvus Qdrant Weaviate Chroma
Docker 单机 需要 etcd + MinIO + Milvus 单容器 单容器 单容器 / 嵌入式
K8s 集群 Helm chart (复杂) Helm chart (简单) Helm chart (中等) 不支持集群
托管服务 Zilliz Cloud Qdrant Cloud Weaviate Cloud
最小部署内存 8GB+ 512MB 2GB 256MB

Docker 快速启动

# Milvus (standalone)
curl -sfL https://raw.githubusercontent.com/milvus-io/milvus/master/scripts/standalone_embed.sh | bash

# Qdrant
docker run -p 6333:6333 -v ./qdrant_data:/qdrant/storage qdrant/qdrant

# Weaviate
docker run -p 8080:8080 -e AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED=true \
  cr.weaviate.io/semitechnologies/weaviate

# Chroma
docker run -p 8000:8000 -v ./chroma_data:/chroma/chroma chromadb/chroma

选型决策矩阵

按团队规模

团队 推荐 理由
个人/原型 Chroma 零配置,Python 原生,学习曲线最低
初创 (< 10人) Qdrant 性能优异,运维简单,一个二进制搞定
中型 (10-100人) Qdrant / Weaviate 按需选择:性能优先选 Qdrant,AI 集成优先选 Weaviate
大型 (100+) Milvus 分布式原生,十亿级向量,GPU 加速

按应用场景

场景 推荐 理由
RAG 应用 Qdrant / Weaviate 过滤+语义搜索,Weaviate 内置 vectorizer 更省事
推荐系统 Milvus 大规模、低延迟、丰富的索引选择
多模态搜索 Milvus / Qdrant 多向量支持,跨模态检索
快速原型 Chroma 嵌入式部署,无需额外服务
混合检索 (BM25 + 语义) Qdrant / Milvus 稀疏+稠密向量支持

迁移路径建议

开发阶段         生产阶段           规模化阶段
Chroma -------> Qdrant ---------> Milvus
(原型验证)      (单机/小集群)      (分布式集群)

由于 API 不互通,迁移需要编写数据导出导入脚本。建议在应用层封装一个 VectorStore 抽象层,隔离底层数据库差异。

总结

没有"最好"的向量数据库,只有"最适合"的。核心决策因素:

  1. 数据规模:百万级以下用 Chroma/Qdrant,亿级以上用 Milvus
  2. 运维能力:运维资源少选 Qdrant,有专职 DBA 可上 Milvus
  3. 开发速度:追求最快上线选 Chroma 或 Weaviate(内置 vectorizer)
  4. 性能要求:单机极致性能选 Qdrant,分布式横向扩展选 Milvus

Maurice | maurice_wen@proton.me