0%

向量数据库深度解析

写在前面

做 RAG(检索增强生成)应用,向量数据库是绕不开的核心组件。市面上产品不少——Milvus、Qdrant、Weaviate、Chroma、Pinecone……每个都说自己最强。到底怎么选?

这篇文章不讲虚的,从底层原理实际选型,重点分析 Chroma 和 Milvus 两款代表产品,让你看完就能做决策。


一、向量数据库解决什么问题

传统数据库擅长精确匹配:WHERE name = '张三'。但语义搜索不一样——用户问”如何提高团队协作效率”,你得找出意思相近的文档,哪怕文档里压根没有这几个词。

向量数据库的核心价值:把文本、图像、音频等非结构化数据转换成向量(一串数字),然后用数学方法计算”相似度”,找出语义最接近的内容。

1
2
文本 → Embedding模型 → 向量 [0.12, -0.34, 0.56, ...] → 向量数据库
查询 → Embedding模型 → 向量 [0.15, -0.30, 0.52, ...] → 相似度计算 → Top-K结果

二、核心技术指标:怎么评判一个向量数据库

1. 索引算法决定性能上限

向量数据库的索引算法直接决定查询速度和召回率。主流索引类型:

索引类型 原理 查询速度 内存占用 适用场景
FLAT 暴力遍历,精确计算 最慢 最高 小数据量,要求100%召回
IVF-FLAT clustering + 倒排 中等 中等 百万级,平衡方案
IVF-PQ 聚类 + 乘积量化压缩 内存受限,牺牲精度
HNSW 分层可导航小世界图 最快 较高 高性能实时查询
DISKANN 磁盘索引 + SSD优化 较慢 极低 超大规模,成本敏感

HNSW 是当前主流选择,它的核心思想是构建一个多层图结构,搜索时从顶层快速跳转,逐层缩小范围,像”跳表”一样高效。

1
2
3
4
5
6
7
8
9
10
11
12
HNSW 结构示意:

Layer 2: ●────────────● (稀疏,快速跳转)
│ │
Layer 1: ●────●───────● (中等密度)
│ │ │
Layer 0: ●─●─●─●─●─●─●─●─● (全量节点,精确搜索)

关键参数:
- M: 每节点最大连接数(默认16),越大越精确但内存越高
- efConstruction: 构建时搜索宽度(默认200)
- efSearch: 查询时搜索宽度,动态调整召回率

2. 分布式架构决定扩展能力

架构类型 代表产品 特点
单机嵌入式 Chroma、Faiss 无部署成本,数据量受限
单机服务化 Qdrant 单机版 独立进程,支持持久化
分布式集群 Milvus、Qdrant 集群 水平扩展,高可用

3. 元数据过滤能力

实际业务中,向量搜索往往要结合条件过滤:找出”价格在100-500元之间且类别是电子产品”的相似商品。

数据库 过滤能力 实现方式
Qdrant 最强 原生支持复杂过滤,性能最优
Milvus 支持标量字段过滤
Chroma 基础 简单 where 条件
Pinecone 元数据命名空间

三、主流向量数据库横向对比

1. 开源产品对比

数据库 语言 架构 索引支持 过滤能力 社区活跃度
Milvus Go 分布式 HNSW/IVF/DISKANN 活跃(CNCF项目)
Qdrant Rust 单机/分布式 HNSW 最强 活跃
Weaviate Go 单机/分布式 HNSW 活跃
Chroma Python 嵌入式 HNSW 基础 活跃

2. 云服务对比

产品 定位 优势 劣势
Pinecone 全托管 Serverless 零运维,自动扩展 供应商锁定,成本不可控
Zilliz Cloud Milvus 托管版 企业级支持,兼容 Milvus API 价格较高
MongoDB Atlas Vector MongoDB 生态 复用现有基础设施 向量能力有限

3. 性能基准(百万级向量,HNSW索引)

数据库 QPS P99延迟 内存占用
Milvus ~15000 ~10ms
Qdrant ~12000 ~8ms
Weaviate ~8000 ~15ms
Chroma ~3000 ~30ms

四、Chroma:轻量级入门首选

1. 为什么选 Chroma

Chroma 的设计哲学是极简:Python 原生、嵌入式运行、API 设计友好。适合以下场景:

  • 原型验证:快速搭建 RAG Demo,几行代码就能跑
  • 小规模应用:文档量 < 10万,单机部署
  • 本地开发:数据不想出本机,隐私可控
  • 学习研究:理解向量数据库基本概念

2. Chroma 核心特性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Chroma 的极简 API 设计
import chromadb

# 初始化:嵌入式,无需启动服务
client = chromadb.PersistentClient(path="./chroma_db")

# 创建集合
collection = client.create_collection(
name="documents",
metadata={"hnsw:space": "cosine"} # 支持 l2、ip、cosine
)

# 添加文档:自动调用 Embedding(内置默认模型)
collection.add(
documents=["文档内容1", "文档内容2"],
ids=["doc1", "doc2"]
)

# 查询:一步到位
results = collection.query(
query_texts=["查询内容"],
n_results=5
)

Chroma 内置 Embedding:默认使用 all-MiniLM-L6-v2 模型,也可以替换为 OpenAI、Cohere 等:

1
2
3
4
5
6
7
8
9
10
11
12
from chromadb.utils import embedding_functions

# 使用 OpenAI Embedding
openai_ef = embedding_functions.OpenAIEmbeddingFunction(
api_key="your-key",
model_name="text-embedding-3-small"
)

collection = client.create_collection(
name="docs",
embedding_function=openai_ef
)

3. Chroma 的元数据过滤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 添加带元数据的文档
collection.add(
documents=["技术文档", "产品文档"],
ids=["d1", "d2"],
metadatas=[
{"category": "tech", "author": "张三"},
{"category": "product", "author": "李四"}
]
)

# 查询时过滤
results = collection.query(
query_texts=["如何部署"],
n_results=5,
where={"category": "tech"} # 只在技术文档中搜索
)

4. Chroma 的局限性

限制 影响
单机架构 无法水平扩展,数据量上限约百万级
索引单一 仅支持 HNSW,无法根据场景切换
过滤简单 不支持复杂布尔组合,性能一般
无分布式 没有副本、分片机制,单点故障风险

一句话总结:Chroma 是向量数据库界的 SQLite——简单好用,但别指望它扛生产级大流量。


五、Milvus:生产级大规模首选

1. 为什么选 Milvus

Milvus 定位是云原生分布式向量数据库,CNCF 沙箱项目。适合以下场景:

  • 大规模生产应用:向量数 > 百万级,甚至亿级
  • 高并发实时检索:要求低延迟、高吞吐
  • 复杂过滤需求:需要结合标量字段过滤
  • 多云部署:支持 Kubernetes、Docker、云服务

2. Milvus 架构解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
┌─────────────────────────────────────────────────────────────┐
│ SDK Layer │
│ Python / Go / Java / Node.js / REST │
├─────────────────────────────────────────────────────────────┤
│ Proxy (接入层) │
│ 负责请求解析、路由、负载均衡 │
├───────────────┬───────────────┬─────────────────────────────┤
│ Query Coord │ Data Coord │ Index Coord │ Root Coord │
│ (查询协调) │ (数据协调) │ (索引协调) │ (总协调) │
├───────────────┴───────────────┴─────────────────────────────┤
│ Query Node Data Node Index Node │
│ (查询执行) (数据写入) (索引构建) │
├─────────────────────────────────────────────────────────────┤
│ etcd (元数据) + MinIO (存储) │
└─────────────────────────────────────────────────────────────┘

核心组件职责:
- Root Coord:全局协调者,处理 DDL(创建集合、索引等)
- Query Coord:查询节点调度,负载均衡
- Data Coord:数据节点调度,segment 管理
- Index Coord:索引构建任务调度

3. Milvus 索引选型实战

不同规模和场景,索引选择策略不同:

数据规模 内存预算 推荐索引 参数建议
< 100万 充足 FLAT 精确搜索,召回率100%
100万-1000万 充足 HNSW M=16, efConstruction=256
100万-1000万 紧张 IVF-FLAT nlist=1024
> 1000万 紧张 IVF-PQ nlist=1024, m=8, nbits=8
> 1亿 极紧张 DISKANN 磁盘索引,SSD必备
1
2
3
4
5
6
7
8
9
10
11
12
13
from pymilvus import MilvusClient, IndexType, MetricType

# 创建 HNSW 索引
index_params = MilvusClient.prepare_index_params()
index_params.add_index(
field_name="vector",
index_type=IndexType.HNSW,
metric_type=MetricType.COSINE,
params={"M": 16, "efConstruction": 256}
)

# 查询参数:动态调整 ef 提高召回率
search_params = {"params": {"ef": 64}} # ef越大,召回率越高,延迟越长

4. Milvus 集合设计最佳实践

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from pymilvus import MilvusClient

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

# 创建集合:向量字段 + 标量字段
client.create_collection(
collection_name="products",
dimension=1536, # OpenAI text-embedding-3-small 维度
metric_type="COSINE",
auto_id=False,
fields=[
{"name": "id", "dtype": "VARCHAR", "max_length": 64, "is_primary": True},
{"name": "vector", "dtype": "FLOAT_VECTOR", "dim": 1536},
{"name": "title", "dtype": "VARCHAR", "max_length": 256},
{"name": "category", "dtype": "VARCHAR", "max_length": 64},
{"name": "price", "dtype": "FLOAT"},
{"name": "created_at", "dtype": "INT64"} # 时间戳
]
)

# 创建标量字段索引(加速过滤)
client.create_index(
collection_name="products",
field_name="category",
index_type="Trie" # 字符串用 Trie,数值用 STL_SORT
)

5. Milvus 过滤查询实战

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 过滤表达式语法
results = client.search(
collection_name="products",
data=[[0.1, 0.2, ...]], # 查询向量
filter='category == "electronics" and price >= 100 and price <= 500',
limit=10,
output_fields=["title", "category", "price"]
)

# 复杂过滤:支持 AND、OR、NOT、IN、LIKE
filter_expr = '''
(category in ["electronics", "books"])
and price > 50
and created_at > 1700000000
'''

6. Milvus 部署方案

部署方式 适用场景 复杂度
Milvus Lite 开发测试,pip 安装 最低
Docker Compose 单机生产,快速部署
Docker + Kubernetes 集群部署,高可用
Zilliz Cloud 全托管,零运维
1
2
3
4
5
6
7
# Docker Compose 快速部署(适合单机生产)
wget https://github.com/milvus-io/milvus/releases/download/v2.4.0/milvus-compose.yml
docker-compose -f milvus-compose.yml up -d

# Milvus Lite 开发测试(Python 直接使用)
pip install milvus
# 自动启动嵌入式 Milvus,无需额外部署

六、选型决策树

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
开始选型

├─ 数据规模多大?
│ ├─ < 10万向量 → Chroma 足够
│ ├─ 10万-100万 → Chroma 单机 / Milvus Lite
│ ├─ 100万-1000万 → Milvus 单机 / Qdrant
│ └─ > 1000万 → Milvus 集群 / Pinecone Serverless

├─ 是否需要强过滤?
│ ├─ 简单过滤 → Chroma / Milvus
│ └─ 复杂过滤 → Qdrant(性能最优)

├─ 是否接受云服务?
│ ├─ 必须本地 → Milvus / Qdrant / Chroma
│ └─ 可以云端 → Pinecone / Zilliz Cloud

├─ 团队技术栈?
│ ├─ Python 主导 → Chroma(最友好)
│ ├─ Go/Rust 主导 → Milvus / Qdrant
│ └─ 已有 MongoDB → Atlas Vector Search

└─ 运维能力?
├─ 无运维团队 → Chroma / Pinecone
├─ 有运维团队 → Milvus / Qdrant

七、实战建议

1. RAG 应用架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
用户查询


Embedding 模型(text-embedding-3-small / bge-large-zh)


向量数据库(Chroma / Milvus)
│ ┌──────────────────────────────────┐
│ │ Collection: documents │
│ │ ├─ vector: [1536 dimensions] │
│ │ ├─ content: 原始文本 │
│ │ ├─ metadata: {source, page, ...} │
│ │ └─ index: HNSW (M=16) │
│ └──────────────────────────────────┘


Top-K 相关文档(K=5~10)


LLM 生成回答(GPT-4 / Claude / DeepSeek)

2. 向量维度选择

Embedding 模型 维度 特点 推荐场景
text-embedding-3-small 1536 OpenAI,通用 英文为主
text-embedding-3-large 3072 OpenAI,更精准 高精度需求
bge-large-zh 1024 中文优化 中文场景
bge-m3 1024 多语言 跨语言场景

注意:维度越高,精度越高,但存储和计算成本也越高。1536维是性价比平衡点。

3. 内存估算

1
2
3
4
5
6
7
单向量存储开销 = 维度 × 4字节 + 元数据开销
索引额外开销 ≈ 基础存储 × 索引系数

示例:100万向量,1536维,HNSW索引
基础存储:1,000,000 × 1536 × 4 = 6.14 GB
索引开销:6.14 × 1.5 ≈ 9.2 GB
总内存需求:约 10 GB

总结

向量数据库选型的核心逻辑:

阶段 推荐方案
原型验证 Chroma,几行代码搞定
小规模生产 Chroma 单机 / Milvus Lite
大规模生产 Milvus 集群 / Qdrant
零运维需求 Pinecone / Zilliz Cloud

Chroma 是入门首选,简单好用,适合快速验证想法。
Milvus 是生产首选,架构成熟,生态完善,能扛大流量。