向量数据库是支撑 RAG(检索增强生成)与语义检索的核心底座。当大模型需要”记忆”海量文档时,关键不是把文字存进 MySQL,而是把文本转成高维向量,再用近似最近邻(ANN)算法在毫秒级找回最相似的内容。本文对比 Milvus 与 Qdrant 两大主流引擎,手把手讲清索引选型、Docker 部署与生产落地要点,帮你少踩坑。
一、向量数据库到底解决什么问题
传统关系型数据库擅长”精确匹配”:WHERE id = 123、WHERE status = 'paid'。但”找出和这句话意思最接近的三段文案”这种语义搜索,靠 B-Tree 索引根本做不到。向量数据库做的事情,是把文本、图片、音频用 Embedding 模型编码成一串浮点数(如 768 维、1536 维),然后在向量空间里做”近邻搜索”。
它和全文检索引擎(如 Elasticsearch)也不是一回事:倒排索引匹配的是”关键词是否出现”,而向量检索匹配的是”语义是否相近”。两者常常互补——先用关键词粗筛,再用向量精排,效果最好。
| 维度 | 关系型数据库 | 全文检索引擎 | 向量数据库 |
|---|---|---|---|
| 查询方式 | 精确等值/范围 | 关键词倒排 | 近似最近邻(ANN) |
| 擅长场景 | 交易、账目 | 日志、站内搜索 | 语义检索、推荐、去重 |
| 典型操作 | SELECT / JOIN | match / term | search(topK, vector) |
| RAG 角色 | 元数据存管 | 粗筛 | 语义召回核心 |
二、核心概念:向量、相似度与索引
2.1 相似度度量
衡量两段向量”多像”,常用三种距离:余弦相似度(只看方向,忽略长度,最常用)、欧氏距离(L2,看绝对距离)、内积(IP,需先归一化)。在 RAG 场景里,余弦相似度几乎成了默认选项,因为它对文本长度不敏感。
2.2 索引类型决定性能与精度
暴力扫描(FLAT)最准但最慢;IVF(倒排文件)把空间聚成若干簇,只搜最近的几个簇,速度快但有损;HNSW(分层可导航小世界图)是当下最主流的近似索引,召回率和延迟都很优秀;DiskANN 则把索引放到磁盘,用少量内存支撑十亿级向量。选错索引,要么慢得不可用,要么召回率掉到无法接受。
import numpy as np
def cosine_similarity(a: np.ndarray, b: np.ndarray) -> float:
# 余弦相似度 = 点积 / (模长乘积),范围 [-1, 1],越大越相似
return float(np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)))
# 假设已用 Embedding 模型得到三个句向量
q = np.random.rand(768)
doc1 = np.random.rand(768)
doc2 = np.random.rand(768)
print(cosine_similarity(q, doc1)) # 例如 0.71
print(cosine_similarity(q, doc2)) # 例如 0.43
# 召回时取相似度最高的 topK 个,就是最朴素、也最可靠的语义检索
关于检索质量的量化评估,可参考本站《向量检索测评实战:Recall@K 与 RAG 质量度量》,用 Recall@K 把”召回得准不准”变成可观测的数字。
三、Milvus 实战:面向规模的分布式向量库
Milvus 是开源向量数据库的”老牌选手”,优势在于水平扩展能力强、生态完整(支持多种索引、支持标量过滤、有 Attu 可视化面板)。它提供 standalone(单机)和 distributed(集群)两种形态,生产环境通常用分布式版扛住十亿级数据。
3.1 用 Docker Compose 起一套 standalone
version: '3.5'
services:
etcd:
image: quay.io/coreos/etcd:v3.5.14
command: etcd -advertise-client-urls=http://etcd:2379 -listen-client-urls http://0.0.0.0:2379
environment:
- ETCD_AUTO_COMPACTION_MODE=revision
- ETCD_AUTO_COMPACTION_RETENTION=1000
minio:
image: minio/minio:RELEASE.2024-05-28
command: minio server /data --console-address ":9001"
environment:
MINIO_ACCESS_KEY: minioadmin
MINIO_SECRET_KEY: minioadmin
milvus:
image: milvusdb/milvus:v2.4.5
command: ["milvus", "run", "standalone"]
ports:
- "19530:19530" # gRPC 端口
- "9091:9091" # 指标端口
depends_on:
- etcd
- minio
上面的编排把 etcd(元数据)、MinIO(对象存储)和 Milvus 本体一起拉起。在本地验证或 CI 里跑集成测试时,这种组合非常顺手,配合 Docker 编排实战 的套路可以快速复现。
3.2 Python 写入与查询
from pymilvus import MilvusClient
client = MilvusClient(uri="http://localhost:19530")
# 创建集合并指定向量维度与索引
if client.has_collection("articles"):
client.drop_collection("articles")
client.create_collection(
collection_name="articles",
dimension=768,
metric_type="COSINE", # 余弦相似度
index_type="HNSW", # 图索引,召回与延迟均衡
index_params={"M": 8, "efConstruction": 200},
)
# 批量插入(实际中来自 Embedding 模型输出)
data = [
{"id": 1, "vector": [0.1] * 768, "title": "微服务治理"},
{"id": 2, "vector": [0.2] * 768, "title": "向量检索入门"},
]
client.insert(collection_name="articles", data=data)
# 语义检索 topK
query_vec = [0.15] * 768
res = client.search(
collection_name="articles",
data=[query_vec],
limit=3,
output_fields=["title"],
)
print(res[0]) # 返回最相似的三条及相似度分数
四、Qdrant 实战:Rust 打造的高性能引擎
Qdrant 用 Rust 编写,以轻量、高吞吐、API 简洁著称,特别适合想把向量检索嵌进现有服务的团队。它同样支持 HNSW、标量过滤、本地磁盘与云端托管,部署成本通常比 Milvus 低。
4.1 启动并建集合
# 一行 Docker 起服务
docker run -p 6333:6333 -p 6334:6334 \
-v /Users/mac/WorkBuddy/网站运营/qdrant_storage:/qdrant/storage \
qdrant/qdrant:latest
from qdrant_client import QdrantClient, models
client = QdrantClient("localhost", port=6333)
client.create_collection(
collection_name="articles",
vectors_config=models.VectorParams(
size=768,
distance=models.Distance.COSINE, # 余弦距离
),
)
# 写入点(payload 可挂任意业务字段,用于过滤)
client.upsert(
collection_name="articles",
points=[
models.PointStruct(id=1, vector=[0.1] * 768, payload={"title": "微服务治理"}),
models.PointStruct(id=2, vector=[0.2] * 768, payload={"title": "向量检索入门"}),
],
)
# 检索 + 标量过滤(只在某些分类里找)
hits = client.query_points(
collection_name="articles",
query=[0.15] * 768,
limit=3,
with_payload=True,
).points
for h in hits:
print(h.id, h.score, h.payload)
五、Milvus vs Qdrant:到底怎么选
| 对比项 | Milvus | Qdrant |
|---|---|---|
| 实现语言 | Go / C++ | Rust |
| 规模上限 | 十亿级、分布式原生 | 千万到亿级、单机够用 |
| 运维复杂度 | 中高(依赖 etcd/MinIO) | 低(单二进制) |
| 生态工具 | Attu 面板、丰富 SDK | Dashboard、REST 友好 |
| 适合场景 | 大型 RAG 平台、多租户 | 中小团队、嵌入式/轻量服务 |
一句话建议:数据量冲亿级、要多人多业务共用,选 Milvus;想快速上线、团队小、追求低运维,选 Qdrant。两者 API 都成熟,后期切换成本主要在数据迁移,不算高。
六、专用向量库 vs pgvector:何时不必上重武器
如果数据量在百万级以内、团队本就重度使用 PostgreSQL,其实没必要单独维护一套向量服务。本站《pgvector 实战:用 PostgreSQL 搞定向量检索与 RAG》已经演示了如何用 SQL 直接做相似度查询,开发与运维链路最短。但当向量规模超过千万、或需要复杂的多向量、稀疏-稠密混合检索时,专用向量库在性能和功能上会更从容。
另外,如果偏好”开箱即用”的轻量方案,也可以看看本站《Chroma 向量数据库实战》与《LlamaIndex 实战:用索引与检索器构建生产级 RAG 应用》,它们更偏原型与嵌入式场景,和 Milvus/Qdrant 形成互补。
七、生产落地检查清单
| 事项 | 要点 |
|---|---|
| 维度对齐 | 写入与查询必须用同一个 Embedding 模型,维度不一致会直接报错 |
| 索引参数 | HNSW 的 M / efConstruction 按数据量与精度需求调,别全用默认 |
| 标量过滤 | 把租户、时间、分类放进 payload/标量字段,避免全量扫描 |
| 一致性 | 确认 insertion 已 flush/可见再查询,CI 里用 GitHub Actions 跑回归 |
| 容量规划 | 单条 768 维 float32 约 3KB,亿级即数百 GB,提前算存储 |
| 可观测 | 暴露 QPS、检索延迟、召回率指标,配合监控告警 |
向量数据库不是银弹,但它确实是当下 AI 应用绕不开的一环。从 pgvector 起步、到 Qdrant/Milvus 进阶,按需升级,比一上来就搭集群要务实得多。




