02.4 - 向量数据库选型与对比
定位: RAG 系统的存储核心——向量数据库的选型直接影响检索性能、运维成本和扩展能力 面试高频度: ⭐⭐⭐⭐ 考查方式: 向量数据库选型、索引类型、性能对比
一、这是什么?为什么需要它?
是什么
向量数据库是专门存储和检索高维向量的数据库系统。在 RAG 中,它存储文档块的 Embedding 向量,并提供高效的近似最近邻(ANN)搜索能力。
传统数据库(SQL):存储结构化数据,精确匹配
查询:name = '张三' -> 精确结果
向量数据库:存储向量,语义匹配
查询:"年假政策" -> 向量化 -> 最相似的 Top-K 文档块为什么需要专门的向量数据库?
| 需求 | 普通数据库 | 向量数据库 |
|---|---|---|
| 语义搜索 | 不支持 | 原生支持 |
| 百万级向量检索 | 全表扫描,极慢 | ANN 索引,毫秒级 |
| 向量+标量混合过滤 | 不支持 | 支持 |
| CRUD 操作 | 支持 | 支持 |
| 横向扩展 | 需手动分片 | 原生分布式 |
二、原理拆解
2.1 向量检索原理
text
暴力搜索(KNN):
计算查询向量与所有存储向量的距离 -> 取 Top-K
复杂度:O(N*d) N=向量数, d=维度
100万向量 * 768维 = 7.68亿次浮点运算 -> 太慢
近似搜索(ANN):
用索引结构减少搜索范围 -> 牺牲少许精度换速度
复杂度:O(log N * d) 或更好
100万向量 -> 几毫秒2.2 主流向量数据库对比
| 特性 | FAISS | Chroma | Pinecone | Weaviate | Milvus | Qdrant |
|---|---|---|---|---|---|---|
| 部署方式 | 本地库 | 本地/进程内 | 托管云 | 自托管/云 | 自托管/云 | 自托管/云 |
| 索引类型 | IVF/ HNSW/ PQ | HNSW | 专有 | HNSW | IVF/ HNSW/ DiskANN | HNSW |
| 持久化 | ❌(内存) | ✅ | ✅ | ✅ | ✅ | ✅ |
| 分布式 | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ |
| 标量过滤 | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 混合搜索 | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ |
| 部署难度 | 简单 | 极简单 | 最简单 | 中 | 复杂 | 中 |
| 适用规模 | 百万级 | 百万级 | 亿级 | 千万级 | 亿级+ | 千万级 |
| 开源 | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ |
| 语言 | Python/C++ | Python | - | Go | Go/C++ | Rust |
| 备份机制 | 手动 | 自动 | 自动 | 自动 | 自动 | 自动 |
2.3 各方案详解
FAISS(Meta):最轻量的选择
- 本质是 Python/C++ 库,不是完整数据库
- 无持久化、无分布式、无过滤
- 适合:原型开发、单机部署、快速验证
python
import faiss
import numpy as np
dimension = 768
index = faiss.IndexFlatL2(dimension) # 暴力检索
# 或
index = faiss.IndexHNSWFlat(dimension, 32) # HNSW 索引,更快
index.add(embeddings) # 添加向量
D, I = index.search(query_vector, k=5) # 检索Chroma:最简单的入门选择
- 进程内运行,无需外部服务
- 自动持久化到磁盘
- 适合:个人项目、小团队、快速原型
python
import chromadb
client = chromadb.Client()
collection = client.create_collection("my_knowledge")
collection.add(
documents=["文档内容1", "文档内容2"],
metadatas=[{"source": "file1.pdf"}, {"source": "file2.pdf"}],
ids=["doc1", "doc2"]
)
results = collection.query(query_texts=["年假政策"], n_results=3)Pinecone:最成熟的全托管方案
- 零运维,自动扩展
- 按使用量付费(较贵)
- 适合:企业生产环境、不想运维
Milvus:企业级分布式方案
- 功能最完整:分布式、多索引、多副本
- 学习成本高,运维复杂
- 适合:大规模生产环境(千万级+)
Weaviate:功能均衡的轻量选择
- CRUD 友好
- 内置向量化模块(可选)
- 适合:需要 http API 的中型项目
2.4 索引类型对比
| 索引类型 | 原理 | 速度 | 精度 | 内存 | 构建时间 |
|---|---|---|---|---|---|
| Flat (暴力) | 全量计算距离 | O(N) | 100% | 高 | 无 |
| IVF | 聚类+缩小搜索范围 | O(log N) | 90-99% | 中 | 中 |
| HNSW | 分层可导航小世界图 | O(log N) | 95-99% | 高 | 长 |
| PQ (乘积量化) | 向量压缩 | O(N) | 80-95% | 低 | 中 |
| DiskANN | 磁盘索引 | O(log N) | 90-95% | 低(磁盘) | 长 |
FAISS 索引选择指南:
python
# 常见 FAISS 索引组合
# 1. 小数据集 (<10万): IndexFlatIP/L2 (暴力,最精确)
index = faiss.IndexFlatIP(dimension)
# 2. 中等数据集 (10万-100万): IndexIVFFlat (IVF+HNSW,快)
index = faiss.IndexIVFFlat(
faiss.IndexFlatL2(dimension), # 量化器
dimension, # 维度
100, # 聚类中心数
faiss.METRIC_L2
)
# 3. 大数据集 (>100万): IndexIVFPQ (压缩,省内存)
index = faiss.IndexIVFPQ(
faiss.IndexFlatL2(dimension),
dimension, 100, 16, 8 # 16字节编码
)2.5 选型决策树
开始选型:
|
+-- 只是本地实验/PoC?
| +-- 数据 < 1万 -> Chroma(最简单)
| +-- 数据 < 100万 -> FAISS(最轻量,无持久化)
|
+-- 小型生产(<100万向量)?
| +-- 不想运维 -> Pinecone(全托管)
| +-- 想自托管 -> Chroma / Weaviate
|
+-- 中型生产(100万-1000万)?
| +-- 想自托管 -> Qdrant / Weaviate
| +-- 全托管 -> Pinecone
|
+-- 大型生产(1000万+)?
+-- 想要全功能 -> Milvus(企业级)
+-- 最简运维 -> Pinecone三、图解全景
RAG 系统向量数据库架构
text
+------------------------------------------------------------------+
| RAG 系统的向量数据库架构 |
| |
| 索引阶段(离线): |
| [文档分块] --Embedding--> [向量 + Metadata] --写入--> [向量数据库] |
| |
| 推理阶段(在线): |
| [用户查询] --查询向量--> [ANN 搜索] --Top-K 块--> [LLM 生成] |
| | |
| 混合过滤 |
| (权限/分类/时间) |
| |
| 运维管理: |
| 备份 -> 索引重建 -> 版本管理 -> 监控报警 |
+------------------------------------------------------------------+四、实战验证
4.1 快速体验:Chroma 与 FAISS
python
# Chroma 快速上手
import chromadb
from chromadb.config import Settings
client = chromadb.Client(Settings(
chroma_db_impl="duckdb+parquet",
persist_directory="./chroma_db"
))
collection = client.create_collection("demo")
# 添加文档
collection.add(
documents=["猫是宠物", "狗是宠物", "地球是行星"],
ids=["1", "2", "3"]
)
# 检索
results = collection.query(
query_texts=["什么动物是宠物"],
n_results=2
)
print(results["documents"])python
# FAISS 快速上手
import faiss
import numpy as np
dimension = 768
index = faiss.IndexHNSWFlat(dimension, 32)
index.hnsw.efConstruction = 200 # 构建时搜索范围
index.hnsw.efSearch = 64 # 检索时搜索范围
# 添加向量(假设已有 embedding)
index.add(embeddings)
# 检索
D, I = index.search(query_embedding, k=5)
print(f"距离: {D[0]}")
print(f"索引: {I[0]}")4.2 性能基准测试思路
bash
# 向量数据库性能测试的核心指标
# 1. 召回率 (Recall@k)
# 在标注数据集上,ANN vs 暴力检索的 Top-K 重合率
# 目标:Recall@10 > 0.95
# 2. 延迟 (Latency)
# p50/p95/p99 检索延迟
# 目标:p95 < 50ms(100万向量级别)
# 3. 吞吐量 (QPS)
# 每秒处理的查询数
# 目标:> 100 QPS(单机)
# 4. 内存/磁盘占用
# 索引大小 / 原始向量大小
# 目标:压缩比 > 5x(使用 PQ 索引)五、面试视角
| 问题 | 答案要点 |
|---|---|
| 向量数据库和传统数据库的区别? | 传统数据库精确匹配;向量数据库用 ANN 索引做近似语义搜索。向量数据库支持高维向量存储和相似度计算 |
| FAISS 为什么适合做 PoC 但不适合生产? | FAISS 是库不是数据库——无持久化、无并发、无分布式、无备份、无过滤。适合快速验证,生产需搭整套服务 |
| HNSW 索引的原理和优缺点? | 分层可导航小世界图——构建多层级图结构,上层长连接快速导航,下层细粒度搜索。优点:速度快精度高;缺点:构建慢、内存大 |
| Chroma 和 Pinecone 的核心差异? | Chroma 本地进程内(简单免费);Pinecone 云托管(无需运维但贵)。Chroma 适合个人/小团队,Pinecone 适合企业生产 |
| 大规模向量检索的挑战? | 1) 内存瓶颈(1亿768维4字节=300GB+);2) 索引构建时间长;3) 频繁写入影响检索;4) 分布式一致性;5) 冷热数据分层 |
| 标量过滤对向量检索性能的影响? | 先过滤后检索(Pre-filter)或先检索后过滤(Post-filter)。Pre-filter 可能漏掉结果,Post-filter 可能浪费计算。推荐使用向量数据库原生的混合过滤机制 |
📚 相关链接
- **Embedding模型与向量化** — 向量数据库中存储的数据来源
- **检索与重排序** — 从向量数据库中检索后如何处理
- **RAG系统部署与监控** — 向量数据库的生产部署
- <- 返回 **检索系统索引**