Skip to content

向量数据库

本页介绍 LLM 应用生态的底层存储基础设施——向量数据库(Vector Database):专门存储和检索高维向量的数据库,是 RAG 检索增强生成的”图书馆”。它解决了传统关键词搜索无法理解语义的问题。

向量数据库 = RAG 的”图书馆”,存的是数学向量而不是文字,用”语义距离”而非”关键词匹配”来检索。

  • 传统搜索(关键词匹配):搜”手机”时找不到写着”智能手机”或”mobile phone”的文档——因为字面不同。
  • 向量搜索(语义匹配):先把每段文字变成一个数学向量(几百到几千维的浮点数数组),语义相近的文字向量也相近。搜”手机”时,“智能手机”的向量离得很近,自然被检索到——理解了意思,而不只是匹配字面。

核心工作流:文字 → 嵌入模型 → 向量 → 存入向量数据库 → 查询时用向量距离找最相似的。

传统数据库(MySQL、PostgreSQL)擅长精确查找——“查找 user_id = 42 的用户”。但语义搜索需要的是相似性查找——“找和这段话意思最接近的 10 段文本”,这要求计算查询向量与数据库中每一个向量的距离。

在百万级甚至十亿级向量中做精确的逐一比较(brute-force)是不可行的:假设有 100 万个 1536 维向量(OpenAI 嵌入维度),每次查询需要 100 万次距离计算,每次涉及 1536 次乘加——即使在现代 CPU 上也需要数秒。向量数据库通过近似最近邻索引将这个时间压缩到毫秒级。

精确最近邻 vs 近似最近邻:精确方法(如 FLAT 索引)逐一比较所有向量,结果 100% 准确但速度慢;近似方法(如 HNSW、IVF)牺牲少量精度(通常 recall@10 > 95%)换取几个数量级的速度提升。实际应用中,ANN 的精度损失几乎不影响 RAG 效果。

嵌入向量(Embedding)是一个固定长度的浮点数数组,例如 [0.023, -0.145, 0.891, ..., 0.034]。这个数组由嵌入模型(如 OpenAI text-embedding-3-small)生成,把文本的语义信息”压缩”到高维空间中。

关键直觉:在这个高维空间中,语义相近的文本对应的空间位置也相近。例如:

  • “猫在睡觉” 的向量 和 “小猫在打盹” 的向量 → 距离很近
  • “猫在睡觉” 的向量 和 “股市今日大跌” 的向量 → 距离很远

这种”语义空间”的几何结构是嵌入模型在训练过程中自动学到的——它通过阅读海量文本,学会了把意思相近的句子映射到相近的坐标。

向量数据库支持多种距离度量(衡量两个向量”远近”的数学函数),选择哪种取决于嵌入模型的训练方式:

  • 余弦相似度(Cosine Similarity):计算两个向量夹角的余弦值,范围 [-1, 1]。值越接近 1 表示方向越一致(语义越相似)。文本嵌入最常用,因为它只关注方向不关注长度,对文本长度变化更鲁棒。公式:cos⁡(A,B)=A⋅B∣A∣×∣B∣\cos(A, B) = \frac{A \cdot B}{|A| \times |B|}
  • 欧氏距离(L2 Distance):两点间的直线距离,值越小越相似。适用于图像嵌入等需要考虑向量”幅度”的场景。公式:d(A,B)=∑(Ai−Bi)2d(A, B) = \sqrt{\sum (A_i - B_i)^2}
  • 内积(Inner Product / Dot Product):当向量已做 L2 归一化(即长度归为 1)后,内积等价于余弦相似度,但计算更快(省去除法步骤)。很多向量数据库默认假设向量已归一化。

⚠️ 距离度量必须与嵌入模型匹配:OpenAI 嵌入模型推荐余弦相似度,部分图像模型推荐 L2 距离。用错度量会导致检索质量大幅下降。

向量数据库的核心技术是近似最近邻(ANN, Approximate Nearest Neighbor)索引。主流 ANN 算法分为三大流派:

HNSW(Hierarchical Navigable Small World)是目前最广泛使用的 ANN 索引算法,几乎所有主流向量数据库都支持。它的核心思想是构建一个多层的近邻图,通过”跳表式”搜索快速逼近目标向量。

直觉理解:想象你在地图上找一家餐厅。你会先看全国地图(最上层,只有少数大城市标记),定位到城市;再看城市地图(中间层,标记了街区),定位到街区;最后看街道地图(最底层,标记了每栋建筑),找到精确位置。HNSW 的多层图结构就是这个思路——上层稀疏(“长途跳转”),下层密集(“精确搜索”)。

算法要点:

  • 多层图结构:每个向量是一个节点。最底层包含所有节点,上层逐层抽样保留少量节点(类似跳表 Skip List)。每个节点与其最近的若干邻居建立边。
  • 搜索过程:从最顶层的某个入口节点开始,贪心地走向离查询向量最近的邻居;到顶层尽头后下降一层继续贪心搜索,直到到达最底层。在最底层做精细的邻居遍历,收集 Top-K 结果。
  • 关键参数:
    • M(连接数):每个节点保留的邻居数,通常 16-48。M 越大,精度越高但内存越大。
    • ef_construction(建图搜索宽度):建图时的候选列表大小,通常 200-500。越大建图越慢但质量越好。
    • ef_search(查询搜索宽度):查询时的候选列表大小,通常 50-200。越大精度越高但查询越慢。

HNSW 的优缺点:

  • ✅ 查询速度极快(通常 < 10ms / 百万级数据)
  • ✅ 召回率高(recall@10 可达 99%+)
  • ✅ 支持动态插入(无需重建索引)
  • ❌ 内存占用大(需要存储图结构 + 原始向量)
  • ❌ 不适合超大规模(10 亿+),因为内存是瓶颈

IVF(Inverted File Index)采用先聚类再搜索的策略:

  1. 训练阶段:用 k-means 聚类将向量空间划分为 nlist 个簇(cluster),每个簇有一个中心点(centroid)。
  2. 分配阶段:将每个向量分配到最近的簇,形成倒排表(inverted list)——每个簇维护一个向量列表。
  3. 查询阶段:先计算查询向量与所有 nlist 个中心的距离,选出最近的 nprobe 个簇,然后只在这些簇内做精确搜索。

直觉理解:像图书馆按主题分区——查”机器学习”相关的书时,不需要翻遍整个图书馆,只需去”计算机科学”区域找。

关键参数:

  • nlist(簇数):通常设为 N\sqrt{N} 到 4N4\sqrt{N}(N 为向量数量)。簇越多,每簇数据越少但中心搜索开销越大。
  • nprobe(探测簇数):查询时搜索的簇数。nprobe 越大精度越高但越慢。通常从 nlist / 100 开始调参。

IVF + PQ 组合:IVF 常与 PQ(Product Quantization,乘积量化)组合使用——先用 IVF 缩小搜索范围,再用 PQ 压缩向量降低内存。这是 FAISS 的经典方案,适合十亿级超大规模数据。

当向量数量达到千万级以上时,内存成为瓶颈。量化技术(Quantization)通过压缩向量来降低内存占用:

  • 乘积量化(PQ, Product Quantization):将高维向量切分成若干子段,每段独立做 k-means 聚类(通常 256 个簇),用簇 ID(1 字节)替代原始浮点数。例如 1536 维向量切分为 8 段,每段 192 维,压缩后只需 8 字节(原始 6144 字节的 0.13%)。精度有损但内存节省巨大。
  • 标量量化(SQ, Scalar Quantization):将 32 位浮点数量化为 8 位整数,直接节省 4 倍内存,精度损失极小。更简单实用,2024 年后被越来越多数据库采用。
  • 二值量化(Binary Quantization):将每个维度的值量化为 1 bit(正数为 1,负数为 0),压缩 32 倍。Milvus 和 Qdrant 在 2024 年都加入了此功能。配合高效的位运算(Hamming 距离),查询速度极快,适合超大规模初筛。
特性HNSWIVFIVF+PQ
查询速度极快快快
召回率极高(99%+)高(95%+)中(90%+)
内存占用大中小
构建速度慢中中
动态更新支持支持需重建
最佳场景百万-千万级千万-亿级十亿级

纯向量搜索并非万能——它擅长语义匹配,但在精确术语、人名、编号等场景下不如关键词搜索。例如搜”GPT-4o-mini”时,向量搜索可能返回 “GPT-4” 或 “GPT-3.5” 的内容(语义相近),而关键词搜索能精确匹配这个型号。

混合检索 = 关键词搜索 + 向量搜索的融合,是 2024-2025 年 RAG 系统的标准实践:

融合方法:

  • RRF(Reciprocal Rank Fusion,倒数排名融合):对每个文档,在两个检索结果中的排名取倒数求和。公式:score(d)=∑1k+ranki(d)\text{score}(d) = \sum \frac{1}{k + \text{rank}_i(d)},其中 kk 通常取 60。RRF 的优势是无需归一化分数,对不同检索器的分数尺度不敏感。
  • 加权平均:对向量相似度和关键词匹配分数做加权平均(如 0.7 × 向量分数 + 0.3 × BM25 分数),权重需调参。

BM25(Best Matching 25):经典的关键词检索算法,基于词频(TF)和逆文档频率(IDF),是 Elasticsearch、Lucene 等搜索引擎的核心。它比纯 LIKE 查询更智能——常见词权重低、罕见词权重高。

实践建议:2025 年的最佳实践是”混合检索 + 重排序”(Hybrid Search + Reranking)。先用混合检索召回 Top-50 候选,再用 Cross-Encoder 重排序模型(如 bge-reranker-v2-m3)精排出 Top-5 喂给 LLM。详见 RAG 检索增强生成。

实际应用中,纯语义搜索往往不够——用户可能只想搜”2024 年的文档”或”技术部的知识库”。向量数据库支持在向量检索的基础上叠加元数据过滤:

# Qdrant 示例:只在过去一年的技术文档中搜索
results = client.query_points(
collection_name="docs",
query=query_vector,
query_filter={
"must": [
{"key": "year", "range": {"gte": 2024}},
{"key": "department", "match": {"value": "技术"}},
]
},
limit=5,
)

过滤的实现策略有两种,各有优劣:

  • Pre-filtering(先过滤后搜索):先按元数据筛出候选集,再在候选集中做向量搜索。过滤性强时效率高,但如果过滤后候选集太小,可能找不到足够的相似向量。
  • Post-filtering(先搜索后过滤):先做向量搜索取 Top-K,再按元数据过滤。可能过滤后结果不足 K 个,需要过度召回。
  • Native filtering(原生前置过滤):Qdrant 等数据库在 HNSW 图遍历时直接跳过不满足条件的节点,效率最高但实现复杂。

向量数据库的核心技术是近似最近邻(ANN)索引:百万级向量里精确计算每个距离太慢,ANN 算法(HNSW、IVF 等)用空间换时间,在”几乎不影响精度”的前提下把检索速度提升几个数量级。

用 ChromaDB 实现文本存储与语义检索

Section titled “用 ChromaDB 实现文本存储与语义检索”
import chromadb
# 1. 创建内存向量库
client = chromadb.Client()
collection = client.create_collection("docs")
# 2. 存入文档(ChromaDB 内置嵌入模型,自动转向量)
collection.add(
ids=["1", "2", "3"],
documents=[
"Python 是最流行的数据科学编程语言。",
"机器学习需要大量标注数据来训练模型。",
"今天天气很好适合户外运动。",
],
)
# 3. 语义检索:找和"深度学习用什么语言"最相关的段落
results = collection.query(
query_texts=["深度学习用什么编程语言?"],
n_results=2, # Top-2
)
for doc, dist in zip(results["documents"][0], results["distances"][0]):
print(f"[距离 {dist:.3f}] {doc}")
# 输出: Python 是最流行的数据科学编程语言。(距离最近)

用 Qdrant 实现带元数据过滤的混合检索

Section titled “用 Qdrant 实现带元数据过滤的混合检索”
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct, Filter, FieldCondition, MatchValue
client = QdrantClient(":memory:") # 内存模式,生产环境用 QdrantClient(host="localhost", port=6333)
# 1. 创建 Collection,指定向量维度和距离度量
client.create_collection(
"knowledge_base",
vectors_config=VectorParams(size=4, distance=Distance.COSINE),
)
# 2. 插入向量(附带元数据 payload)
client.upsert(
"knowledge_base",
points=[
PointStruct(id=1, vector=[0.1, 0.2, 0.3, 0.4],
payload={"category": "tech", "year": 2024}),
PointStruct(id=2, vector=[0.15, 0.25, 0.35, 0.45],
payload={"category": "tech", "year": 2023}),
PointStruct(id=3, vector=[0.9, 0.8, 0.7, 0.6],
payload={"category": "sports", "year": 2024}),
],
)
# 3. 带过滤条件的向量搜索:只在 2024 年的 tech 类文档中搜
results = client.query_points(
"knowledge_base",
query=[0.1, 0.2, 0.3, 0.4],
query_filter=Filter(
must=[
FieldCondition(key="category", match=MatchValue(value="tech")),
FieldCondition(key="year", match=MatchValue(value=2024)),
]
),
limit=5,
)
for point in results.points:
print(f"ID={point.id}, score={point.score:.3f}, payload={point.payload}")

用 pgvector 在 PostgreSQL 中做向量检索

Section titled “用 pgvector 在 PostgreSQL 中做向量检索”

pgvector 的优势是不需要额外部署向量数据库——直接在现有的 PostgreSQL 上安装扩展即可:

-- 1. 安装扩展
CREATE EXTENSION vector;
-- 2. 创建带向量列的表
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
content TEXT,
category TEXT,
embedding VECTOR(1536) -- OpenAI text-embedding-3-small 维度
);
-- 3. 创建 HNSW 索引
CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops);
-- 4. 插入数据(embedding 由应用层生成后传入)
INSERT INTO documents (content, category, embedding)
VALUES ('Python 是数据科学的首选语言', 'tech', '[0.1, 0.2, ...]');
-- 5. 语义搜索 + 元数据过滤,一条 SQL 搞定
SELECT content, 1 - (embedding <=> '[0.15, 0.25, ...]') AS similarity
FROM documents
WHERE category = 'tech'
ORDER BY embedding <=> '[0.15, 0.25, ...]' -- <=> 是余弦距离操作符
LIMIT 10;

pgvector 0.7+(2024 年发布)支持 HNSW 索引和半精度浮点存储,性能已接近专用向量数据库。对于中小规模数据(< 1000 万向量),“PostgreSQL + pgvector” 是性价比最高的选择。

用 FAISS 构建高性能单机向量检索

Section titled “用 FAISS 构建高性能单机向量检索”
import faiss
import numpy as np
# 生成模拟数据:100 万个 768 维向量
dimension = 768
n_vectors = 1_000_000
vectors = np.random.random((n_vectors, dimension)).astype('float32')
faiss.normalize_L2(vectors) # L2 归一化,使内积 = 余弦相似度
# 方案一:HNSW 索引(高精度,内存大)
index = faiss.IndexHNSWFlat(dimension, 32) # M=32
index.hnsw.efConstruction = 200
index.hnsw.efSearch = 64
index.add(vectors)
# 方案二:IVF + PQ 索引(省内存,适合超大规模)
quantizer = faiss.IndexFlatIP(dimension)
index_ivf = faiss.IndexIVFPQ(quantizer, dimension, nlist=4096, m=64, nbits=8)
index_ivf.train(vectors)
index_ivf.add(vectors)
index_ivf.nprobe = 64 # 查询时探测 64 个簇
# 查询
query = np.random.random((1, dimension)).astype('float32')
faiss.normalize_L2(query)
distances, indices = index.search(query, k=10)
print(f"Top-10 索引: {indices[0]}")
print(f"相似度分数: {distances[0]}")
  • 选择合适的距离度量:文本嵌入用余弦相似度(或归一化后的内积),图像嵌入用 L2 距离。度量选错会严重拖垮检索质量。务必查看嵌入模型的文档确认推荐度量。
  • HNSW 是默认首选:如果你不确定用哪种索引,就用 HNSW。它在大多数场景下提供了最佳的精度-速度平衡。只有当数据量超过内存容量时,才考虑 IVF+PQ。
  • 批量插入而非逐条插入:向量数据库的索引构建有批量优化。逐条插入数万条数据可能比批量插入慢 10 倍以上。建议每批 1000-10000 条。
  • 嵌入向量要归一化:使用余弦相似度时,确保向量已 L2 归一化。很多嵌入模型(如 OpenAI text-embedding-3)默认输出已归一化的向量,但开源模型不一定。
  • 注意嵌入维度与成本:嵌入维度越高,存储和检索开销越大。OpenAI text-embedding-3-large 支持”降维”参数(如从 3072 维降到 256 维),在精度损失可控的前提下大幅降低成本。
  • 合理设置 Top-K:RAG 场景通常召回 Top-5 到 Top-20 喂给 LLM。K 太大会引入噪声(降低回答质量),K 太小可能漏掉相关信息。配合重排序模型时可以先召回 Top-50 再精排。
  • 评估检索质量用 Recall@K:不要只看速度。构建一个标注好的问答测试集,测量”正确答案在 Top-K 结果中的比例”(Recall@K),这是检索系统最核心的指标。
  • 监控索引碎片化:频繁的插入和删除会导致 HNSW 图碎片化,查询性能逐渐下降。定期重建索引或使用支持自动合并的数据库(如 Qdrant)。
  • 考虑多租户隔离:SaaS 场景下不同用户的数据应隔离。大多数向量数据库支持 Collection 级别或 Payload 过滤级别的隔离。Collection 级隔离更安全但管理开销大。
  • RAG 知识库:企业文档、FAQ、手册全部嵌入向量库,用户提问时秒级检索相关段落喂给 LLM——所有 RAG 产品的存储底座。详见 RAG 检索增强生成。
  • 推荐系统:把用户和商品都表示为向量,找”最相似的商品”推荐——向量检索是现代推荐引擎的核心组件。
  • 图片语义搜索:用 CLIP 模型(OpenAI 的多模态嵌入模型,能同时编码图像和文本)把图片编码为向量,“以图搜图”或”以文搜图”——Pinterest、电商平台的相似商品推荐都基于此。
  • 去重与相似度检测:在海量文本/代码中找出语义重复或高度相似的内容——论文查重、代码抄袭检测、新闻聚类。
  • AI Agent 的长期记忆:Agent 将历史交互存为向量,后续从过往经验中检索相关案例——这是 Agent 记忆系统的主流实现方案。详见AI Agent 与多智能体。
  • 多模态 RAG:文本、图片、音频、视频统一嵌入到同一向量空间,用户可以用文字搜图片、用图片搜文档——跨模态检索是 2024-2025 年的热门方向。
类库语言说明
ChromaDBPython轻量开源向量数据库,开发原型首选,内置嵌入模型
PineconeSaaS托管型向量数据库,生产级规模与低延迟,免运维
WeaviateGo / Python开源向量搜索引擎,支持混合检索(关键词 + 向量)和模块化嵌入
MilvusGo / Python开源分布式向量数据库,支持十亿级向量,多种索引类型
QdrantRust高性能开源向量数据库,Rust 编写,过滤能力强,支持 Binary Quantization
FAISSPython / C++Meta 开源的高效向量检索库,单机性能标杆,无服务端,适合算法研究
pgvectorSQLPostgreSQL 向量扩展插件,在已有数据库上加向量检索,0.7+ 支持 HNSW
LanceDBPython / Rust基于 Lance 列式存储格式的嵌入式向量数据库,适合多模态数据
VespaJava开源搜索与推荐引擎,支持向量检索 + 排序 + 实时更新,适合复杂搜索场景
术语英文解释
向量嵌入Embedding把文本/图像转换为固定长度的数值向量,语义相近则向量相近
余弦相似度Cosine Similarity衡量两个向量方向一致性的指标,值越接近 1 越相似
欧氏距离Euclidean Distance (L2)两点之间的直线距离,值越小越相似
近似最近邻ANN (Approximate Nearest Neighbor)牺牲少量精度换取大幅加速的向量检索算法
HNSW 索引HNSW (Hierarchical Navigable Small World)基于分层图的高效 ANN 索引,查询速度与精度的主流选择
倒排文件索引IVF (Inverted File Index)先聚类再在簇内搜索的 ANN 方法,适合超大规模数据
乘积量化PQ (Product Quantization)将向量切分为子段独立压缩,大幅节省内存的量化技术
标量量化SQ (Scalar Quantization)将 32 位浮点数量化为 8 位整数,节省 4 倍内存,精度损失极小
二值量化Binary Quantization将每个维度量化为 1 bit,压缩 32 倍,配合 Hamming 距离极速查询
混合检索Hybrid Search关键词检索与向量检索的融合,兼顾精确匹配与语义理解
倒数排名融合RRF (Reciprocal Rank Fusion)将多个检索结果列表按排名倒数融合的经典算法
BM25BM25 (Best Matching 25)基于词频和逆文档频率的经典关键词检索算法
维度Dimension向量的长度,嵌入模型通常输出 768-3072 维
召回率Recall@K衡量检索质量的指标:正确答案出现在 Top-K 结果中的比例
  • FAISS:Johnson et al., “Billion-scale similarity search with GPUs”(2017),Meta 开源的高效向量检索库,单机/单 GPU 上性能标杆。
  • HNSW:Malkov & Yashunin, “Efficient and robust approximate nearest neighbor search using Hierarchical Navigable Small World graphs”(2018/2020),现代向量数据库最广泛采用的索引算法,论文详细描述了多层图的构建和搜索策略。
  • Product Quantization:Jégou et al., “Product quantization for nearest neighbor search”(IEEE TPAMI 2011),PQ 量化的奠基论文,解释了如何通过子空间分解实现高压缩比。
  • 向量数据库综述:Pan et al., “Survey of Vector Database Management Systems”(2024),系统对比 ChromaDB / Pinecone / Milvus / Weaviate / Qdrant 等主流方案的功能和性能。
  • 混合检索:Cormack et al., “Reciprocal Rank Fusion outperforms Condorcet and individual Rank Learning Methods”(SIGIR 2009),RRF 算法的原始论文,证明了简单的排名融合优于复杂的机器学习方法。
  • pgvector:Greenplum/pgvector 仓库,2024 年 0.7 版本引入 HNSW 索引和半精度浮点支持,使 PostgreSQL 成为中小规模向量检索的实用选择。
  • FAISS 教程:Meta AI Research 维护的 FAISS Wiki,包含从入门到十亿级索引的完整教程和性能调优指南。