Skip to content

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 主流向量数据库对比

特性FAISSChromaPineconeWeaviateMilvusQdrant
部署方式本地库本地/进程内托管云自托管/云自托管/云自托管/云
索引类型IVF/ HNSW/ PQHNSW专有HNSWIVF/ HNSW/ DiskANNHNSW
持久化❌(内存)
分布式
标量过滤
混合搜索
部署难度简单极简单最简单复杂
适用规模百万级百万级亿级千万级亿级+千万级
开源
语言Python/C++Python-GoGo/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系统部署与监控** — 向量数据库的生产部署
  • <- 返回 **检索系统索引**

Knowledge4J — Java 知识库