向量数据库
向量数据库是 AI 时代新增的数据层组件,专门存储高维向量(Embedding)并提供近似最近邻搜索(ANN),是 RAG、语义检索、以图搜图的核心基础设施。
为什么需要专门的向量数据库
传统数据库(MySQL / ES):
- 精确匹配(WHERE id = 123)
- 关键词匹配(LIKE '%关键词%')
- 倒排索引(全文搜索)
向量数据库:
- 语义匹配("猫" 和 "kitten" 距离相近)
- 跨模态匹配(文字 ↔ 图片)
- 高维空间相似度搜索(k=10 最近邻)
核心模型
文本 / 图片 / 音频
│
▼
Embedding 模型
│ text-embedding-3-large、BGE、CLIP
▼
高维向量(768 / 1024 / 1536 / 3072 维浮点数组)
│
▼
向量数据库
│ 存储 + 索引
▼
查询时:query 向量 → 找 Top-K 最相似向量
关键概念:
| 概念 | 说明 |
|---|---|
| Vector / Embedding | 高维浮点数组,表示语义 |
| Distance Metric | 距离度量:Cosine(余弦)/ L2(欧式)/ Dot Product |
| ANN(Approximate NN) | 近似最近邻,牺牲精度换速度 |
| Recall | 召回率,正确结果占返回结果比例 |
| QPS | 每秒查询数 |
ANN 索引算法
精确最近邻在百万级以上数据量时不可行(O(N)),生产环境都用近似算法:
| 算法 | 原理 | 特点 |
|---|---|---|
| HNSW | 分层小世界图 | 综合最优,主流选择 |
| IVF | 倒排文件 + 聚类 | 内存占用低 |
| IVF-PQ | IVF + 乘积量化 | 极致省内存,精度略降 |
| ScaNN | Google 出品,量化 + 各向异性 | 高精度高性能 |
| LSH | 局部敏感哈希 | 简单,精度较差 |
| DiskANN | 磁盘索引 | 数据量超大时使用 |
HNSW 简化示意:
Layer 2: ●─────────● 稀疏层(远距离跳跃)
│ │
Layer 1: ●──●──●──● 中间层
│ │ │ │
Layer 0: ●●●●●●●●●●●●● 全节点(精细搜索)
查询:
1. 从顶层开始,找最近邻节点
2. 下沉一层,继续搜索更近的节点
3. 在最底层找到 Top-K
主流方案对比
| 方案 | 语言 | 索引 | 特点 | 适用场景 |
|---|---|---|---|---|
| Qdrant | Rust | HNSW | 高性能、过滤强、云原生 | 生产首选 |
| Milvus | Go+C++ | HNSW/IVF/DiskANN | 多种索引、分布式 | 大规模(10亿+) |
| pgvector | C(PG 插件) | IVFFlat / HNSW | 复用 PG 事务和 SQL | 中小规模、简单部署 |
| Weaviate | Go | HNSW | GraphQL API、模块化 | 知识图谱 |
| Chroma | Python | HNSW | 嵌入式、轻量 | 本地开发、原型 |
| Pinecone | 闭源 SaaS | 专有 | 全托管、零运维 | 不想自建的团队 |
| Elasticsearch | Java | HNSW(8.x+) | 全文 + 向量混合 | 已有 ES 集群 |
| Redis Stack | C | HNSW | 与 Redis 缓存复用 | 已用 Redis |
Qdrant 架构(推荐)
┌─────────────────────────────────────────┐
│ Qdrant Cluster │
│ │
│ Node 0 Node 1 Node 2 │
│ │
│ Collection: documents │
│ ├── Shard 0 (Primary, Replica) │
│ ├── Shard 1 (Primary, Replica) │
│ └── Shard 2 (Primary, Replica) │
│ │
│ Vectors + Payload(结构化元数据) │
└─────────────────────────────────────────┘
核心特性:
- Payload 过滤:向量 + 结构化字段联合查询(“找最相似且 user_id=123”)
- 量化压缩:Scalar / Product / Binary Quantization,省 4~32 倍内存
- 预过滤优化:先过滤再向量搜索,避免低效后过滤
- MMR / Diversity:保证返回结果多样性
示例:插入和查询
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct, Filter
client = QdrantClient(host="qdrant", port=6333)
client.create_collection(
collection_name="docs",
vectors_config=VectorParams(size=1536, distance=Distance.COSINE),
)
client.upsert(
collection_name="docs",
points=[
PointStruct(
id=1,
vector=[0.05, 0.12, ...],
payload={"text": "K8s 入门", "tag": "k8s"},
),
],
)
results = client.search(
collection_name="docs",
query_vector=[0.04, 0.10, ...],
query_filter=Filter(must=[{"key": "tag", "match": {"value": "k8s"}}]),
limit=10,
)典型应用场景
RAG(检索增强生成)
用户提问:"K8s 怎么扩容?"
│
▼
Embedding(提问 → 向量)
│
▼
向量库检索 Top-10 相关文档片段
│
▼
Reranker 精排(CrossEncoder / BGE-Reranker)
│
▼
拼接 Prompt:[相关片段] + 用户问题
│
▼
LLM 生成答案
详见 AI 云原生。
语义搜索
替代传统关键词搜索:
- 用户搜 “电动车续航差” → 也能匹配到 “EV 电池衰减” 的文章
- 跨语言:中文 query 匹配英文文档(多语言 Embedding 模型)
以图搜图 / 图文检索
用 CLIP 模型,文本和图片映射到同一向量空间:
图片1 → CLIP image 编码 → 向量 → 入库
"一只橘猫" → CLIP text 编码 → 向量 → 检索 → 返回相似图片
推荐系统召回
用户 Embedding(基于历史行为)
│
▼
向量检索 Top-200 候选商品
│
▼
精排模型(CTR / LTR) → Top-20 推荐
异常检测
将用户行为编码成向量,异常请求与正常分布距离远,触发告警。
混合检索(Hybrid Search)
只有向量召回有时不够精准,结合关键词检索效果更好:
用户 query "K8s Pod 调度"
│
├── 向量召回(语义相似)→ Top-50
└── BM25 召回(关键词)→ Top-50
│
▼
Reciprocal Rank Fusion(RRF 合并排序)
│
▼
Reranker 精排 → Top-10
Qdrant、Weaviate、Elasticsearch 都已原生支持混合检索。
性能优化
| 优化 | 说明 |
|---|---|
| 量化压缩 | float32 → int8 / 1bit,省 4~32 倍内存 |
| HNSW 参数调优 | M、ef_construction、ef 三者平衡精度/速度 |
| 预过滤索引 | Payload 字段建索引,过滤前置 |
| 分片 + 副本 | 横向扩容,多副本提升 QPS |
| 冷热分层 | 热向量内存,冷向量 SSD/磁盘(DiskANN) |
| 异步写入 | 批量写入,索引后台构建 |
K8s 部署
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: qdrant
spec:
serviceName: qdrant
replicas: 3
template:
spec:
containers:
- name: qdrant
image: qdrant/qdrant:latest
ports:
- containerPort: 6333 # HTTP
- containerPort: 6334 # gRPC
volumeMounts:
- name: storage
mountPath: /qdrant/storage
resources:
requests:
memory: "8Gi"
cpu: "2"
limits:
memory: "16Gi"
cpu: "4"
volumeClaimTemplates:
- metadata:
name: storage
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 100Gi生产建议:
- 使用 StatefulSet(向量索引有状态)
- 内存要充足(向量大头在内存)
- SSD 存储(IO 密集)
- 配合 Operator(如 Qdrant Operator)自动化运维
与 ES / 关系库的关系
| 维度 | 关系库 | ES | 向量库 |
|---|---|---|---|
| 数据类型 | 结构化 | 文档 + 倒排索引 | 高维向量 |
| 查询 | 精确 / SQL | 全文 / 聚合 | 相似度 / kNN |
| 主键 | ID | _id | Point ID |
| 关联 | JOIN | 父子文档 | 无(Payload 内嵌) |
| 一致性 | ACID | 近实时(1s) | 近实时 |
现代架构通常是三者并存:
- 关系库存事务数据(订单、用户)
- ES 提供全文搜索 + 聚合分析
- 向量库提供语义搜索 + AI 检索
注意事项
- Embedding 模型一致性:写入和查询必须用同一个模型(否则向量空间不同)
- 维度匹配:1536 维向量不能查 768 维空间
- Distance 选择:用 Cosine 时向量需 L2 归一化
- 冷启动:向量库不像 ES 有倒排索引压缩,1 亿条 1536 维约 600GB,需要量化
- 过滤性能:复杂 Payload 过滤可能比向量搜索还慢,要建索引
- 版本管理:换 Embedding 模型 = 整库重建,要预留迁移方案