向量数据库
是什么
向量数据库是专门为存储、索引和检索高维向量而设计的数据库系统。它的核心能力是相似性搜索:给定一个查询向量,快速找出数据库中与之最相似的向量。
传统数据库:SELECT * WHERE name = '张三' → 精确匹配
向量数据库:找出与"这张猫的图片"最相似的前10张图片 → 语义匹配
为什么需要向量数据库
Embedding向量 将文本、图像等非结构化数据转换为向量后,需要一个能高效处理这些向量的存储系统。
传统数据库的局限
| 需求 | 传统数据库 | 向量数据库 |
|---|---|---|
| 存储百万级向量 | 可以,但慢 | 专门优化 |
| 相似度搜索 | 需全表扫描,O(n) | ANN索引,近似O(log n) |
| 语义查询 | 不支持 | 核心功能 |
| 实时更新+检索 | 支持 | 支持(部分产品更优) |
核心概念
ANN(近似最近邻搜索)
精确最近邻(KNN)需要与所有向量逐一比较,百万级数据下极慢。
ANN(Approximate Nearest Neighbor) 用少量精度损失换取极大速度提升:
精确KNN:查100万条,耗时 1000ms,准确率 100%
ANN: 查100万条,耗时 5ms,准确率 95%
主流索引算法
HNSW(Hierarchical Navigable Small World)
- 构建多层图结构,高层稀疏导航,低层精确搜索
- 优点:查询速度快,精度高
- 缺点:内存占用大,构建慢
- 使用:Pinecone、Weaviate、Qdrant 默认算法
层级结构示意:
Layer 2: A -------- E (稀疏,快速导航)
Layer 1: A -- C -- E -- G
Layer 0: A-B-C-D-E-F-G-H (稠密,精确搜索)
IVF(Inverted File Index)
- 先用 K-Means 聚类,查询时只搜索最近的几个簇
- 优点:内存友好,适合超大规模
- 缺点:需要预训练,精度略低
- 使用:Faiss 常用配置
PQ(Product Quantization,乘积量化)
- 将向量压缩存储,大幅减少内存
- 常与 IVF 组合:IVF+PQ
- 适合:内存受限场景
LSH(Locality Sensitive Hashing)
- 用哈希函数将相似向量映射到同一桶
- 优点:实现简单
- 缺点:精度较低,已逐渐被 HNSW 取代
距离度量
| 度量方式 | 公式 | 适用场景 |
|---|---|---|
| 余弦相似度 | cos(θ) = A·B / (|A||B|) | 文本语义(最常用) |
| 欧氏距离 | √Σ(aᵢ-bᵢ)² | 图像、推荐系统 |
| 点积 | A·B | 归一化向量等价余弦 |
| 曼哈顿距离 | Σ|aᵢ-bᵢ| | 稀疏向量 |
主流向量数据库对比
| 产品 | 类型 | 特点 | 适用场景 |
|---|---|---|---|
| Faiss | 库(非独立DB) | Meta出品,极致性能,无服务端 | 研究、嵌入式 |
| Chroma | 开源,嵌入式/服务端 | 轻量,开发友好,Python原生 | 本地RAG开发 |
| Qdrant | 开源,独立服务 | Rust编写,高性能,支持过滤 | 生产RAG |
| Weaviate | 开源,独立服务 | 内置模块化,支持混合搜索 | 企业级 |
| Pinecone | 云服务(闭源) | 全托管,开箱即用 | 快速上线 |
| Milvus | 开源,分布式 | 超大规模,云原生 | 亿级向量 |
| pgvector | PostgreSQL扩展 | 已有PG可直接用 | 小规模,简化架构 |
选型建议
本地开发/原型 → Chroma(最简单)
生产环境/中等规模 → Qdrant(性能+易用平衡)
已有PostgreSQL → pgvector(减少组件)
超大规模(亿级)→ Milvus
不想运维 → Pinecone
核心功能
基本操作
# 以 Chroma 为例
import chromadb
client = chromadb.Client()
collection = client.create_collection("my_docs")
# 插入向量
collection.add(
embeddings=[[0.1, 0.2, ...], [0.3, 0.4, ...]],
documents=["文档内容1", "文档内容2"],
ids=["doc1", "doc2"]
)
# 相似性查询
results = collection.query(
query_embeddings=[[0.15, 0.25, ...]],
n_results=5 # 返回最相似的5条
)
混合搜索(Hybrid Search)
结合向量相似度和关键词匹配,效果优于单独使用任一方式:
混合搜索 = α × 向量相似度得分 + (1-α) × BM25关键词得分
支持混合搜索的产品:Weaviate、Qdrant、Elasticsearch(with kNN)
元数据过滤
向量搜索 + 结构化条件过滤,避免语义漂移:
# 只在"技术文档"类别中搜索,且发布时间在2024年后
results = collection.query(
query_embeddings=[query_vector],
where={"category": "技术文档", "year": {"$gte": 2024}},
n_results=10
)
在 RAG 中的工作流程
【离线建库】
原始文档
→ 分块(Chunking)
→ Embedding 模型生成向量
→ 存入向量数据库(向量 + 原文 + 元数据)
【在线检索】
用户问题
→ Embedding 模型生成查询向量
→ 向量数据库 ANN 搜索 → Top-K 相关文档块
→ 注入 LLM Prompt
→ LLM 生成回答
分块策略(Chunking)
分块质量直接影响检索效果:
| 策略 | 说明 | 适用 |
|---|---|---|
| 固定大小 | 每块512 token,50 token重叠 | 通用 |
| 按段落/章节 | 保持语义完整性 | 结构化文档 |
| 递归分块 | 先大块后小块,保留层级 | 长文档 |
| 语义分块 | 按语义边界切分 | 高质量要求 |
性能关键指标
| 指标 | 说明 |
|---|---|
| QPS | 每秒查询数,衡量吞吐量 |
| Recall@K | Top-K结果中真实最近邻的比例,衡量精度 |
| 延迟 P99 | 99%请求的响应时间 |
| 索引构建时间 | 数据导入后建立索引的耗时 |
| 内存占用 | 索引驻留内存大小 |
向量数据库 vs 其他存储
| 对比 | 向量数据库 | 关系型数据库 | 搜索引擎(ES) |
|---|---|---|---|
| 查询类型 | 语义相似 | 精确/范围 | 关键词全文 |
| 数据类型 | 高维向量 | 结构化 | 文本 |
| 扩展性 | 水平扩展 | 垂直为主 | 水平扩展 |
| 语义理解 | 强 | 无 | 弱(词频统计) |
实际生产中常组合使用:向量数据库做语义检索 + 关系型数据库存业务数据。