向量数据库:Milvus 原理与实战

向量数据库:Milvus 原理与实战

向量数据库是 RAG 系统的记忆中枢——Embedding 把文档变成向量,它负责高效存储和检索。

为什么普通数据库不够用

暴力搜索的问题

100万个向量逐一计算余弦相似度需要 2~5 秒,无法满足实时检索需求。

ANN(近似最近邻搜索)

不逐个比较,快速找到近似最优解

指标 暴力搜索 ANN 检索
100万向量耗时 2~5秒 1~10毫秒
召回率 100% 95%~99%
适用数据量 <10万 百万~亿级

ANN 以略微降低召回率为代价,换来 1000 倍以上的速度提升,在生产环境中是必选项。

主流索引算法

1. IVF(倒排文件索引)

先把向量分成若干簇,检索时只搜最近的几个簇。

2. HNSW(分层可导航小世界图)⭐ 最主流

多层图结构,从粗到细逐层搜索:

1
2
3
4
5
Layer 2:    A ──────── E ──────── G        ← 粗筛,大步长
Layer 1: A ── B ── C ── D ── E ── F ── G ← 中筛
Layer 0: A──B──C──D──E──F──G──H──I──J──K ← 精筛,小步长

搜索起点

优点:速度快、精度高、参数少
缺点:内存占用大(比原始向量多 2~3 倍内存)

主流向量数据库对比

数据库 适用数据量 语言 SDK 开源 适用场景
Milvus 百万~十亿级 Java/Python/Go 大规模生产环境
Qdrant 百万~亿级 Python/Rust/Go 高性能单机
Weaviate 百万~千万级 Python/Go/Java 内置向量化
Pinecone 百万~亿级 Python/Node.js 纯云托管
Chroma <百万 Python/JS 原型验证
pgvector <百万 PostgreSQL 已有 PG

为什么选 Milvus

  1. 开源且社区活跃 - Apache 2.0,42.8k+ star
  2. Java SDK 完善 - 本系列代码示例首选
  3. 支持大规模数据 - 几万到几十亿都能应对
  4. 索引类型丰富 - HNSW、IVF、DISKANN 等
  5. 标量过滤能力强 - 支持元数据过滤
  6. 本地部署简单 - docker compose 即可启动

Milvus 核心概念

Milvus 概念 MySQL 对应 说明
Collection Table 数据基本组织单位
Schema 表结构 定义字段名、类型、约束
Field Column 单个字段
Partition 分区表 按业务维度划分数据
Index 索引 加速检索

快速上手:Docker 部署 Milvus

1
2
3
4
5
6
7
8
9
# 下载 docker-compose 配置
wget https://github.com/milvus-io/milvus/releases/download/v2.4.0/milvus-standalone-docker-compose.yml
mv milvus-standalone-docker-compose.yml docker-compose.yml

# 启动
docker-compose up -d

# 验证
curl "http://localhost:9091/healthz"

实战:Python 操作 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
27
28
29
from pymilvus import MilvusClient, CollectionSchema, FieldSchema, DataType

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

# 创建 Collection
client.create_collection(
collection_name="rag_docs",
dimension=1024, # BGE-M3 向量维度
)

# 插入数据
client.insert(
collection_name="rag_docs",
data=[
{"id": 1, "vector": [0.1] * 1024, "text": "退货政策内容...", "doc_name": "退货政策.pdf"},
{"id": 2, "vector": [0.2] * 1024, "text": "物流配送说明...", "doc_name": "物流规则.pdf"},
]
)

# 检索
results = client.search(
collection_name="rag_docs",
data=[[0.1] * 1024], # 查询向量
limit=5,
output_fields=["text", "doc_name"]
)

for result in results[0]:
print(f"ID: {result['id']}, 文本: {result['entity']['text']}")

在 RAG 流程中的位置

1
2
数据准备:文本块 → 向量化 → 存入 Milvus Collection
检索阶段:用户问题 → 向量化 → Milvus ANN 检索 → Top-K 结果

相关阅读: