摘要
高维向量数据库是面向非结构化数据语义理解与近似最近邻(Approximate Nearest Neighbor, ANN)检索专门设计的数据基础设施。其核心任务是将文本、图像、音频等非结构化数据转化为高维向量,在支撑海量向量高并发、低时延相似度检索的同时,提供标量属性过滤、实时动态写入与分布式一致性保障。
一个完备的向量检索系统涵盖离线特征加工(文档解析、切分、Embedding 编码、索引构建)与在线查询执行(Query 改写、多路召回、标量过滤、排序融合与精排)。系统工程的核心并不是单纯追求算法跑得最快,而是在相关性、召回率(Recall)、查询时延(p99 Latency)、吞吐量(QPS)、内存/磁盘成本以及写入可见性之间取得最佳的工程权衡(Trade-off)。
本文围绕两大主线展开:
- 基础技术:Embedding 表征原理、距离与相似度度量,以及主流内存 ANN 索引算法(IVF、PQ、HNSW 等);
- 系统实践:SSD 磁盘驻留型索引(DiskANN、SPANN)、查询执行引擎与稀疏/稠密混合检索架构。
1. 向量数据库与向量检索系统
1.1 问题定义与核心场景
传统关系型数据库擅长精确条件匹配(如 status = 1 AND price < 500),全文搜索引擎依赖倒排索引(Inverted Index)做关键词精确匹配。然而,这两类系统都基于字面符号比对,无法直接度量语义、视觉或概念层面的相似程度。
向量检索旨在解决高维空间中的“找最近邻”问题:给定查询向量 $q \in \mathbb{R}^d$ 与向量数据集 $V = {v_1, v_2, \ldots, v_N} \subset \mathbb{R}^d$,依据特定距离度量函数找出最相似的 $K$ 个近邻(Top-K)。
典型应用场景包括:
- 大模型 RAG(检索增强生成)与知识库:根据用户问题的语义,从知识库中检索最相关的文档切片(Chunks);
- 推荐系统召回:基于双塔模型产出的用户兴趣向量与物品特征向量,在千万级候选池中快速初筛;
- 跨模态与多媒体搜索:以文搜图、以图搜图、以音频搜内容;
- 样本去重与聚类:发现近重复内容、相似样本或异常行为模式;
- 风控与安全审计:实时比对行为特征向量与已知风险模式的偏离程度。
1.2 单机 ANN 算法库与生产级向量数据库
Faiss、ScaNN、Hnswlib 等单机 ANN 算法库专注于内存中高维向量的近邻搜索,核心优势在于底层计算指令(AVX-512、NEON、CUDA)的极致性能优化。但应用层需要自行处理数据持久化、实时增量写入、分布式分片扩展与故障恢复。
生产级向量数据库(如 Milvus、Qdrant 等)将 ANN 算法作为底层执行引擎的计算算子,并在外围构建了完整的分布式存储与服务体系:
┌─────────────────────────────────────────────────────────────┐
│ Access & Gateway Layer │
│ (API / RPC, Authentication, Rate Limiting, Routing) │
├─────────────────────────────────────────────────────────────┤
│ Coordination Plane │
│ (Metadata, Sharding, Replica Scheduling, Consistency) │
├─────────────────────────────────────────────────────────────┤
│ Execution Engine │
│ (Real-time Ingestion, Hybrid ANN, Filtering, Compaction) │
├─────────────────────────────────────────────────────────────┤
│ Storage Hierarchy │
│ (WAL Log, Columnar Scalars, Inverted Lists, Graph/Disk) │
└─────────────────────────────────────────────────────────────┘
- 接入与路由层:提供统一 API/RPC 接口、鉴权、多租户隔离、请求路由与分片结果汇总(Scatter-Gather);
- 控制与协调层:管理元数据,调度数据分片(Shards)、副本(Replicas)与负载均衡;
- 计算与执行层:负责实时写入接收、动态索引构建、标量过滤、多路召回融合与精排打分;
- 存储与持久化层:管理预写日志(WAL)、不可变数据段(Segments)、列式标量存储与分层索引文件。
| 维度 | 单机 ANN 算法库(如 Faiss) | 生产级向量数据库 |
|---|---|---|
| 核心定位 | 高性能近邻搜索算法内核 | 向量检索 + 标量管理 + 分布式在线服务 |
| 数据与生命周期 | 仅管理向量数组与内部 ID,更新需应用自行组织 | 支持 Schema、完整 CRUD、元数据管理与版本控制 |
| 持久化与弹性 | 需应用手动保存/加载索引文件 | WAL 日志持久化、自动分片、副本容灾与水平扩缩容 |
| 查询表达力 | 基础 Top-K 向量检索 | 向量检索、标量条件过滤、全文本/稀疏混合检索与精排流水线 |
| 适用场景 | 离线分析、学术评测、静态小规模原型 | 线上高并发业务、持续写入与权限隔离场景 |
1.3 核心数据流
向量检索系统通常包含离线/流式入库与在线检索两条解耦的数据链路:

- 入库链路:原始文本/文件经清洗、解析后切分为固定大小的切片(Chunks);Embedding 模型将切片编码为高维向量;向量连同原始 Payload、标量属性(权限、时间戳、分类标签)一起写入数据库,并在后台构建向量索引、标量倒排与稀疏索引。
- 检索链路:在线查询经规范化改写后,通过同源同配置的 Embedding 模型转为查询向量;系统并行执行 ANN 向量检索与标量过滤(或稀疏检索),在候选集上进行精确距离重算、属性回表、多路融合与 Cross-Encoder 精排,最终返回 Top-K 结构化结果。
2. Embedding:语义空间的数学表征
2.1 映射机制与误差分层
Embedding 本质上是一个将非结构化数据映射为 $d$ 维实数向量的特征提取器:
$$ f_\theta: \mathcal{X} \to \mathbb{R}^{d} $$
其中 $\mathcal{X}$ 表示输入数据(文本、图像、音频等),$\theta$ 为模型参数。训练良好的模型会让语义相似的对象在空间中距离更近,无关对象距离更远。
在排查检索效果不佳时,应先区分是表示问题(切分清洗不佳或模型不匹配)还是检索问题(索引剪枝丢了候选):
- 表示问题:由文本切分破坏上下文、清洗残留噪音、切片过长稀释主题,或 Embedding 模型缺乏垂直领域理解能力引起。如果某条相关文档用最精确的暴力扫描(KNN)都排不进前几名,说明向量本身的语义生成就有问题,此时调大 HNSW 的
efSearch等索引参数也无济于事; - 检索问题:由 ANN 索引的近似剪枝引起。表现为暴力全量扫描能够找到目标文档,但 ANN 索引为了追求性能提前截断了搜索路径,导致漏召回。
2.2 文本向量化流水线:从 Chunk 到稠密向量
在最常见的单向量检索模式中,文本转换为向量的标准链路如下:
$$\text{原始文档} \xrightarrow{\text{结构解析}} \text{Chunk 切片} \xrightarrow{\text{分词}} \text{Token 序列} \xrightarrow{\text{Transformer}} H \in \mathbb{R}^{L \times d} \xrightarrow{\text{Pooling}} v_{\text{chunk}} \xrightarrow{\text{归一化}} v \in \mathbb{R}^d$$
形式化表达为:
$$ v = \operatorname{Normalize}\left(\operatorname{Project}\left(\operatorname{Pool}\left(\operatorname{Encoder}_{\theta}(\operatorname{Tokenize}(x))\right)\right)\right) $$
原始文本: "向量数据库用于大规模近似搜索"
│
▼ Tokenizer (分词与词表映射)
Token IDs: [101, 3142, 6205, 3315, 2099, ...] + Position IDs + Attention Mask
│
▼ Transformer Encoder (多层 Self-Attention 交互)
隐层矩阵 H: [h_1, h_2, ..., h_L] (每个 token 对应一个 d 维上下文向量)
│
▼ Pooling (将变长 token 序列聚合为定长向量)
定长向量: v_chunk = MeanPool(H) 或 v_chunk = H[CLS]
│
▼ Linear Projection & L2 Normalization (线性投影与归一化)
最终向量: v = v_chunk / ||v_chunk||_2
2.2.1 内部机制分解
- 分词与序列编码:Tokenizer 将文本切分为长度为 $L$ 的 Token 序列,映射为词表 ID 并附加位置编码与注意力掩码(Attention Mask)。
- 上下文建模(Contextual Encoding):Transformer 编码器通过多层自注意力机制捕捉 Token 间的深层语义依赖: $$ \operatorname{Attention}(Q, K, V) = \operatorname{softmax}\left(\frac{QK^{T}}{\sqrt{d_k}}\right)V $$ 输出隐层状态矩阵 $H = [h_1, h_2, \ldots, h_L] \in \mathbb{R}^{L \times d}$,其中每个 Token 向量 $h_i$ 都融合了上下文语义。
- 序列池化(Pooling):ANN 索引要求每条记录对应固定维度的向量,因此需要将变长序列 $H$ 压缩为一个 $d$ 维向量。常用池化方式:
- Mean Pooling(均值池化):对所有非 padding 的 token 向量取均值(最常用); $$ v_{\text{chunk}} = \frac{\sum_{i=1}^{L} m_i h_i}{\sum_{i=1}^{L} m_i} \quad (m_i \in {0, 1} \text{ 为 Attention Mask}) $$
- CLS Token Pooling:直接取预训练特有的
[CLS]位置对应的向量 $h_0$; - Last Token Pooling:常用于由自回归大模型(如基于 Qwen/Llama 系列)改造的 Embedding 模型。
- 线性投影与 L2 归一化:通过线性层微调维度,并进行 L2 归一化使向量长度为 1($|v|_2 = 1$),方便后续直接用内积计算余弦相似度。
需要注意的是,预训练语言模型(如原生 BERT)直接输出的向量有一个天然缺陷:所有文本生成的向量都会扎堆挤在同一个极窄的方向上,导致无论什么句子彼此算出来的相似度都高达 0.85 以上,根本拉不开区分度。因此现代 Embedding 模型都必须通过专门的对比学习训练,把无关文本强行推开、把相似文本拉近,让向量在整个空间中分布得更分散均匀,距离计算才具有实际辨识度。
2.2.2 表征模型技术选型对比
| 表征类型 | 典型代表 | 机制与输出形态 | 存储与检索特性 | 适用场景 |
|---|---|---|---|---|
| 静态词向量 | Word2Vec, GloVe | 查表映射,每个词对应固定向量 | 极低计算开销,但无法区分多义词,表达能力弱 | 词级相似度分析、轻量规则过滤 |
| 稠密单向量 | BGE-dense, text-embedding-3, E5 | Transformer 编码 + Pooling,输出单一固定长度稠密向量 | 检索效率高,高度适配主流 ANN 索引(HNSW/IVF) | 语义搜索、企业级 RAG、通用推荐召回 |
| 学习型稀疏向量 | SPLADE, BGE-M3 Sparse | 模型预测全词表维度的非零权重,附带语义词项扩展 | 适配倒排索引,兼具精确词项匹配与泛化扩展能力 | 含有专有名词、产品型号的关键词敏感检索 |
| 多向量延迟交互 | ColBERT, BGE-M3 ColBERT | 保留 Token 级多个隐层向量,检索时执行 Late Interaction(MaxSim) | 细粒度语义匹配极强,但向量存储与检索计算成本成倍增加 | 高精度文档检索、重排阶段候选细筛 |
| 多模态对齐表征 | CLIP, ALIGN, ImageBind | 双塔/多塔架构将文本、图像、音频映射至统一共享度量空间 | 支撑跨模态直接度量(文搜图、图搜文) | 多模态内容理解、电商视觉搜索 |
2.2.3 语义对比学习训练
检索模型通常采用对比学习(Contrastive Learning)训练。给定查询 $q$、正例文档 $d^+$ 以及负例集合 ${d^-j}{j=1}^M$,采用 InfoNCE 损失函数进行优化:
$$ \mathcal{L} = -\log \frac{\exp(s(q, d^+) / \tau)}{\exp(s(q, d^+) / \tau) + \sum_{j=1}^{M} \exp(s(q, d^-_j) / \tau)} $$
其中 $s(u, v)$ 为相似度函数(如余弦相似度),$\tau$ 为温度超参数。该目标拉近相关文本在空间中的距离,推开不相关文本,使相似度在几何距离上直接可比。
- 双塔模型(Bi-Encoder):查询与文档独立编码。文档向量可以离线预先算好并存入索引,在线检索时只用编码一次查询,能支撑亿级海量数据的毫秒级召回;
- 交叉编码器(Cross-Encoder):查询与文档拼在一起输入模型,通过全自注意力层让两者的每个词充分交互,打分更准,但每次比较都要重新跑一次深度前向推理,无法预计算,因而只适合在小候选集上做精排。
2.3 影响表征质量的工程因素
- 分块策略(Chunking Strategy):文本切片太长会稀释核心主题,太短则丢失上下文。工程上建议依据语义边界(标题层级、段落边界、Markdown 语法节点)进行切分,并设置 10%~20% 的重叠滑动窗口(Overlap),防止切分断句导致上下文丢失。
- 向量维度权衡:维度越高能表达的信息越细致,但会线性增加内存占用、磁盘 I/O 及距离计算开销。应结合业务数据上的召回-时延曲线选型;部分模型支持 MRL(俄罗斯套娃嵌入),允许按需截取前 256/512 维使用以节省资源。
- 领域适配与微调:通用模型在面对垂直领域的专业术语、产品型号、医疗代码等时容易产生偏差,需要用业务数据做针对性微调,或引入关键词稀疏检索做兜底互补。
- 元数据溯源与版本治理:向量数据需记录
embedding_model_name、model_version及切片 ID,便于后续模型平滑升级或增量重算。
3. 向量检索算法:从精确 KNN 到近似近邻(ANN)
3.1 距离度量与计算优化
给定两个 $d$ 维向量 $x, y \in \mathbb{R}^d$,常用的相似度与距离度量函数如下:
| 度量类型 | 数学定义 | 取值范围 | 判定准则 | 适用场景 |
|---|---|---|---|---|
| 欧氏距离(L2) | $|x - y|2 = \sqrt{\sum{i=1}^d (x_i - y_i)^2}$ | $[0, +\infty)$ | 距离越小越相似 | 聚类分析、坐标类嵌入、向量模长具有独立物理意义的场景 |
| 余弦相似度 | $s_{\cos}(x, y) = \frac{x \cdot y}{|x|_2 |y|_2}$ | $[-1, 1]$ | 夹角余弦越大越相似 | 文本语义检索(重点关注方向,忽略文本长度导致的模长差异) |
| 内积(IP) | $x \cdot y = \sum_{i=1}^d x_i y_i$ | $(-\infty, +\infty)$ | 内积值越大越相似 | 双塔召回打分、已归一化向量快速检索、推荐系统评分 |
若向量预先做过 L2 归一化($|x|_2 = |y|_2 = 1$),欧氏距离平方与内积存在简单的线性换算关系:
$$ |x - y|_2^2 = |x|_2^2 + |y|2^2 - 2(x \cdot y) = 2 - 2(x \cdot y) = 2 - 2 s{\cos}(x, y) $$
此时,最大化余弦相似度、最大化内积与最小化欧氏距离在排序结果上完全等价。工程上通常先将向量做 L2 归一化,检索时直接调用 CPU SIMD 的 FMA 指令做点积运算,既省去了开平方计算,又能最大化硬件吞吐。
3.2 精确近邻搜索(Exact KNN)
精确 K 近邻搜索(Brute-force / Flat Search)遍历数据集中全部 $N$ 个向量,逐一计算与查询向量 $q$ 的距离,并通过大小为 $K$ 的堆找出全局最优解:
$$ \operatorname{KNN}(q, K) = \operatorname{arg,topK}_{v \in V} s(q, v) $$
- 计算复杂度:全量距离计算耗时为 $O(N \cdot d)$,Top-K 堆维护开销为 $O(N \log K)$;
- 工程定位:无需预先训练或构建索引,零额外内存开销,结果绝对精确($\text{Recall} = 100%$)。在小规模数据集(如 $N \le 50{,}000$)或离线评测(生成标准评测真值集 Ground Truth)中作为基准参考;但在海量在线高并发场景下,受限于算力与内存带宽瓶颈无法直接使用。
3.3 近似最近邻(ANN)与高维检索挑战
当数据规模 $N$ 增长到千万甚至十亿级时,暴力全量扫描的时延无法满足线上实时要求。近似最近邻(Approximate Nearest Neighbor, ANN)算法通过牺牲极少量的精度,换取数量级的检索速度提升。
3.3.1 召回率评测指标
ANN 的准确度通常用 $\text{Recall}@K$ 来衡量:
$$ \text{Recall}@K = \frac{|\operatorname{ANN}_K(q) \cap \operatorname{Exact}_K(q)|}{K} $$
评估 ANN 系统时不能只看单次查询耗时,而应绘制 Recall–Latency 权衡曲线(或 Recall–QPS 曲线),评估在达到业务目标召回率(例如 $\text{Recall}@10 \ge 95%$)时系统的实际时延与资源开销。
3.3.2 为什么传统树形索引在高维下会失效
在低维空间($d \le 10$)中,KD-Tree 等基于空间划分的树形索引可以做到 $O(\log N)$ 的检索速度。但在高维空间($d \ge 128$)中:
- 距离趋同效应:任意两点间的距离差值占距离总值的比例越来越小,点与点之间的远近差异被弱化;
- 空间划分剪枝失效:查询点周围的搜索超球体很容易同时跨越多个划分超平面,导致树形索引无法有效排除无关分支,最终退化为全量回溯扫描(复杂度恶化为 $O(N)$)。因此现代高维 ANN 算法主要采用近邻图导航与聚类量化两大技术路线。
3.4 主流 ANN 算法技术路线横向对比
| 算法家族 | 代表实现 | 核心机制 | 优势 | 主要代价与约束 | 核心调优参数 |
|---|---|---|---|---|---|
| 暴力线性扫描 | Flat | 内存全量扫描 + SIMD/GPU | 绝对精确、零建索引耗时、支持即时更新 | 算力与时延随规模线性增长 | batch_size, 硬件并行度 |
| 倒排文件索引 | IVF-Flat | K-Means 聚类空间胞元,检索时探查临近簇列表 | 构建快速、易于与标量过滤组合 | 需要预训练聚类中心,数据倾斜影响性能 | nlist(簇总数), nprobe(探查簇数) |
| 乘积量化 | PQ / OPQ | 子空间分解 + 码本离散化,查表近似距离 | 内存占用极低(压缩 8~16 倍),内存带宽压力小 | 存在量化精度损失,需二次精排 | 子空间数 m, 码本比特数 nbits |
| 倒排乘积量化 | IVF-PQ | IVF 空间粗筛 + PQ 码压缩存储与扫描 | 亿级规模下兼顾低内存与高吞吐 | 调参复杂,召回率依赖候选重排 | nlist, nprobe, m, nbits |
| 分层近邻图 | HNSW | 多层跳表式可导航小世界图(NSW) | 极高召回率、超低查询时延、支持增量插入 | 内存消耗大(边指针),删除与重构成本高 | M(节点度数), efConstruction, efSearch |
| SSD 驻留图 | DiskANN (Vamana) | SSD 存储大图与向量,DRAM 缓存导航节点与 PQ | 单机单节点支撑十亿级规模,大幅削减 DRAM 成本 | 强依赖 NVMe 随机读取性能与异步 I/O 调度 | 图度数 R, 搜索宽度 L, PQ 压缩比 |
| 混合磁盘倒排 | SPANN | 内存驻留聚类质心,SSD 存储变长倒排链 | 适配内存受限场景,高吞吐批量检索 | 边界样本冗余复制,索引构建耗时长 | 质心数, 探查列表数, 复制阈值 |
3.5 倒排索引(IVF):空间聚类与局部扫描
IVF(Inverted File Index)的核心思路是通过无监督聚类将连续高维空间划分为若干局部区域(Voronoi 胞元):
[K-Means 空间聚类]
Voronoi 胞元 1 Voronoi 胞元 2
┌────────────────┐ ┌────────────────┐
│ Centroid 1 │ │ Centroid 2 │
│ * * * │ │ * * * │
└───────┬────────┘ └───────┬────────┘
│ │
▼ Posting List 1 ▼ Posting List 2
[ v_12, v_45, v_98 ] [ v_3, v_18, v_77 ]
- 训练与建索引:对全量数据采样并运行 K-Means 聚类,生成
nlist个聚类中心(Centroids)。每个向量被分配并写入距离最近的中心点对应的倒排链表(Posting List)中; - 在线检索:计算查询向量 $q$ 与所有
nlist个中心点的距离,挑选最近的nprobe个簇,随后只在这几个倒排链表中扫描向量并收集 Top-K。
nlist(中心点数量):nlist越大,每个倒排列表越短,单簇扫描越快,但搜索中心点本身的开销也会增加;nprobe(探查簇数):核心调优参数。nprobe = 1时只查最近的一个簇;调大nprobe可以避免查询点刚好落在两个簇的分界边缘时漏召回,提高召回率,但会相应增加计算耗时。
3.6 乘积量化(PQ)与非对称查表加速
Product Quantization(PQ)是一种有损的高维向量压缩技术,将高维向量切分为多个低维子向量分别进行量化。
原始 128 维 Float32 向量 (512 Bytes)
┌──────────────┬──────────────┬──────┬──────────────┐
│ Sub-vec 1 │ Sub-vec 2 │ ... │ Sub-vec 16 │ (每段 8 维)
└──────┬───────┴──────┬───────┴──────┴──────┬───────┘
│ │ │
▼ (查子码本) ▼ (查子码本) ▼ (查子码本)
Byte Code 1 Byte Code 2 Byte Code 16
┌──────────────┬──────────────┬──────┬──────────────┐
│ 0x4A │ 0x1F │ ... │ 0xE2 │ (压缩为 16 Bytes)
└──────────────┴──────────────┴──────┴──────────────┘
- 子空间划分:将 $d$ 维向量均匀切成 $m$ 个低维子向量;
- 子码本聚类:对每个子空间分别聚类生成 256 个中心点(每个中心用 1 字节即 8 bit 编码即可表示);
- 向量压缩:原向量用 $m$ 个 1-Byte 的量化 ID 替代,内存占用从 $4d$ 字节压缩至 $m$ 字节(例如 768 维 Float32 向量由 3072 字节压缩至 96 字节,压缩比达 32 倍)。
非对称距离计算(ADC, Asymmetric Distance Computation)
检索时,查询向量 $q$ 不进行量化(保持浮点精度),仅库内向量使用压缩码。系统先计算 $q$ 的各子向量到对应 256 个质心的距离,在内存中生成一张 $m \times 256$ 的查找表(LUT):
$$ \widetilde{d}(q, v)^2 = \sum_{j=1}^m \operatorname{LUT}_j\left[\operatorname{code}_j(v)\right] $$
计算 $q$ 与某个库内压缩向量的距离时,无需做任何浮点乘加运算,直接执行 $m$ 次查表累加即可估算距离。
- OPQ(Optimized PQ):在分段前先对向量空间进行全局旋转变换,使各子空间的方差更均衡,减少量化误差;
- SQ(Scalar Quantization 标量量化):对每个维度单独做浮点压缩(如 Float32 $\to$ INT8/FP16),无需训练码本,提供 2~4 倍轻量压缩;
- 工程标准范式:“PQ/SQ 压缩召回 + 原向量精排重打分(Filter-and-Refine)”:先用压缩向量在海量数据中快速粗筛出前 100~200 个候选,再回读这批候选的原始高精浮点向量重新精确计算距离,消除量化造成的排序颠倒。
3.7 分层可导航小世界图(HNSW)
HNSW(Hierarchical Navigable Small World)是当前内存向量检索中综合性能领先的图索引算法。其核心借鉴了跳表(Skip-List)的思想,将近邻图构建为多层拓扑结构。
Layer 2 (稀疏长跨度跳跃)
(Entry) o ───────────────────────────────> o
Layer 1 (中等跨度导航)
o ─────────────> o ─────────────> o ───────> o
Layer 0 (密集近邻细粒度搜索)
o ───> o ───> o ───> o ───> o ───> o ───> o ───> o
3.7.1 算法运行机制
- 多层拓扑构建:底层(Layer 0)包含全部数据节点,节点间建立局部近邻连接;上层按照概率抽取部分节点建图,层数越高,节点越稀疏、边跨度越大;
- 由粗到细的贪心寻径:查询从最高层的全局入口点(Entry Point)出发,在当前层沿距离逐步变近的方向快速大步跳跃;当在当前层走到局部最近点后,下沉到下一层继续搜索,直至底层 Layer 0,在目标邻域内执行细粒度扩展搜索。
3.7.2 关键超参数
M:控制底层节点的最大连边数。增大M能提升图连通性与召回上限,但会增加内存指针开销与建图耗时;efConstruction:建图时的搜索宽度。调大该值使得建图时探索得更全面,生成的图质量更高,但会降低索引构建速度;efSearch:在线查询时的候选队列探索深度(需满足 $\text{efSearch} \ge K$)。调大efSearch可在不重建索引的情况下直接提升查询召回率,代价是轻微增加查询时延。
3.7.3 HNSW 的工程痛点与动态维护
- 内存额外开销:除了存原始向量,每个节点还要存各层的邻居指针链表(通常额外占用 20%~100% 内存);
- 动态删除困难:图中的节点充当了导航路标的作用,直接硬删除节点会导致路径断裂、形成孤岛,影响召回率。生产中常用的解决方案包括:
- 墓碑标记(Soft Delete):检索时通过位图过滤跳过已删除节点,但保留其图连通结构(内存不即时释放);
- 后台整理(Compaction):定期在后台剔除被标记的节点并修补断开的邻接边;
- 数据段全量重建(Segment Rebuild):类似 LSM-Tree 机制,积累一定更新量后在后台生成新的静态 Segment。
3.8 局部敏感哈希(LSH)与随机投影树(Annoy)
- LSH(Locality-Sensitive Hashing):通过特殊的哈希函数,让距离相近的向量有较大概率发生哈希碰撞并落入同一个桶中。为了保证召回通常需要建多张哈希表。在低维稀疏特征场景理论完备,但在现代深度稠密向量场景中,其综合召回与时延表现已不及图索引。
- Annoy(Approximate Nearest Neighbors Oh Yeah):利用随机超平面将空间递归二分,生成一组随机投影树森林。其最大优势是索引文件结构完全静态,支持内存映射(
mmap),多个进程可直接共享同一块物理内存,非常适合只读、静态数据的轻量化部署。但构建完成后不支持在线动态插入数据。
4. 磁盘驻留索引与 I/O 架构优化
4.1 内存瓶颈与存储分层动因
当向量规模达到千万至十亿级时,全量驻留内存会带来沉重的硬件成本。以 10 亿条 768 维 Float32 向量为例:
$$ 10^9 \times 768 \times 4\text{ Bytes} \approx 3.07\text{ TB (裸向量存储)} $$
如果加上 HNSW 的图连边指针(约 1.5 TB)以及元数据和查询缓存,单节点内存需求将超过 5 TB。
借助 NVMe SSD 极高的并发随机读能力(数十万至百万级 IOPS)与低成本优势,磁盘驻留型 ANN 索引通过冷热分层存储,把主要数据下沉到 SSD,单台服务器即可支撑十亿级规模的向量检索。
4.2 磁盘 ANN 系统的核心设计原则
┌─────────────────────────────────────────────────────────────┐
│ DRAM (内存层) │
│ [全局导航入口] [紧凑 PQ/SQ 压缩表示] [热点节点 LRU 缓存] │
└──────────────────────────────┬──────────────────────────────┘
│
NVMe SSD 异步批量 I/O (io_uring / O_DIRECT)
│
┌──────────────────────────────▼──────────────────────────────┐
│ NVMe SSD (持久化磁盘层) │
│ [4KB 扇区对齐图节点: 邻接边 + 原生高维 Float32 向量共置] │
└─────────────────────────────────────────────────────────────┘
- 分层数据放置(Memory-Disk Hierarchy):导航入口、高频热点节点以及全量 PQ/SQ 压缩向量常驻内存;完整的高精度原始向量和庞大的邻接表存放在 SSD;
- 内存快速粗筛:在内存中先用压缩向量(PQ/SQ)查表快速估算距离,锁定候选区域后再去读磁盘,避免产生过多无效的磁盘 I/O;
- 限制随机 I/O 次数(I/O Budget):通过 Beam Search 严格限制单次查询向 SSD 发起的随机读取跳数;
- 4KB 扇区对齐与数据共置(Colocation):将每个图节点的邻接指针列表与该节点对应的原始高精度向量打包存放在同一个 4KB 扇区块内。一次 4KB 随机读即可同时取回连边信息与特征向量,消除二次回表带来的读放大;
- 异步流水线并发 I/O:使用 Linux
io_uring或 AIO 进行非阻塞批量读取,充分发挥 NVMe 设备的高队列深度(Queue Depth)来掩盖物理硬件的读取时延; - 候选集精确精排:从磁盘读出少量候选节点的原始 Float32 向量重算精确距离,消除量化误差。
4.3 DiskANN / Vamana 体系
DiskANN 是基于 SSD 架构的图索引代表,其核心是 Vamana 图拓扑算法:
- Vamana 剪枝策略:引入可调参数 $\alpha \ge 1$。在为节点挑选邻居时,算法不仅挑选局部距离最近的点,还兼顾保留提供“长距离快捷跨越”的互补方向节点。相比 HNSW 的多层跳表,Vamana 构建出的单层图兼具大步跨越与局部细搜能力;
- 协同检索流水线:在内存中用 PQ 压缩码进行快速路径规划与 Beam Search;沿 Vamana 拓扑向 SSD 异步并发拉取对齐节点;最后读取候选节点的原始 Float32 向量完成精确重排。DiskANN 实现了单台 64GB 内存服务器支撑 10 亿级向量的毫秒级检索。
4.4 SPANN:内存质心与磁盘倒排
SPANN 采用内存-磁盘混合倒排架构:
- 内存质心路由:在内存中维护数十万个细粒度聚类中心(Centroids);
- 磁盘变长倒排链:底层海量向量的原始数据存储在 SSD 的倒排列表(Posting Lists)中;
- 边界向量冗余复制(Boundary Replication):建索引时,将处于空间分界边缘的向量同时写入多个临近簇;在线检索时只需探查 1~2 个最相关的倒排链,大幅减少磁盘读取次数。
4.5 磁盘索引工程优化清单
- 多级缓存协同:结合入口常驻、热点节点 LRU 缓存、操作系统的 Page Cache 与直接 I/O(Direct I/O),重点关注 p99 尾延迟;
- 存储对齐:严格按物理扇区大小(4KB/8KB)对齐存储块,避免跨扇区读取引发二次 I/O;
- 异步预取:在 Beam Search 遍历过程中,根据当前候选队列提前预取下一批最可能访问的节点数据;
- 冷热分层与后台合并(Compaction):新写入数据先进入内存可变段(MemTable),达到阈值后刷盘为不可变段(Immutable Segment),后台异步执行 Segment Merge 与垃圾清理。
5. 查询执行引擎与精排流水线
5.1 标准查询生命周期
生产级向量查询包含多阶段复合执行流水线:
用户 Query
│
▼
[1. Query 改写与规范化] ── (纠错、指代消解、HyDE 扩展)
│
▼
[2. Query 向量化] ── (同源模型推理 + L2 归一化)
│
▼
[3. 协同过滤与候选召回] ── (执行 ANN 超额召回: K_cand = 5~10 * K)
│
▼
[4. 标量校验与去重/分组] ── (租户隔离、属性约束、SPU/Doc 分组)
│
▼
[5. 多级精排打分] ── (Float32 距离精确重算 / Cross-Encoder)
│
▼
最终 Top-K 结果集
候选池超额召回(Over-sampling):在初筛阶段通常设置召回倍率 $\beta = 3 \sim 10$(即召回 $K_{\text{cand}} = \beta \cdot K$),为后续标量条件过滤、业务去重及深度精排预留候选余量。
5.2 查询改写(Query Rewrite)
Embedding 模型的输入质量直接影响向量匹配效果。查询改写的工程目标是消除用户输入的歧义性与口语化偏差,使查询文本的表达方式更贴近语料库,从源头提高查询向量的判别力。
| 改写策略 | 核心机制 | 典型应用场景 | 成本与工程考量 |
|---|---|---|---|
| 词法规范化 | 拼写纠错、停用词过滤、同义词扩展、繁简及全半角归一 | 输入存在拼写错误、口语化简称 | 计算开销极低(词典/规则驱动),线上默认开启 |
| 会话指代消解 | 结合多轮上下文历史,补全代词与省略主谓语 | 多轮 RAG 问答(如“它支持哪些系统” $\to$ “Milvus 2.4 支持哪些系统”) | 依赖轻量 SLM 或规则,增加 5~20ms 时延 |
| 假设文档嵌入 (HyDE) | 利用 LLM 基于 Query 生成一段假设性回答,将回答向量化用于检索 | 长文档匹配短问题(缩小问句与文档之间的表达差距) | 引入一次 LLM 推理(100~500ms),成本高,需配合 Query 缓存 |
| 意图拆解与子查询 | 将复合问题拆分为多个单意图子 Query 并行检索 | 比较类问题(如“对比 HNSW 与 DiskANN 的优缺点”) | 多路并发检索,需在汇聚层进行多路合并与去重 |
5.3 标量过滤与混合执行策略
生产环境中向量检索几乎始终伴随标量元数据约束(如 tenant_id = "A" AND created_at >= 1700000000)。
┌──────────────────────────────────────────────┐
│ 标量过滤执行模式对比 │
└──────────────────────────────────────────────┘
[前过滤 Pre-Filtering] [后过滤 Post-Filtering]
全量数据 全量数据
│ (标量索引条件筛选) │ (ANN 向量检索)
▼ ▼
候选 ID 集合 (可能很小) Top-M 候选 (如 M=100)
│ (在子集上做向量搜索) │ (过滤掉不符合条件的记录)
▼ ▼
最终 Top-K (易破坏图连通性) 最终结果 (可能不足 K 条)
────────────────────────────────────────────────────────────
[单遍迭代过滤 Single-Stage Iterative Filtering] (生产主流)
在 ANN 图遍历 / 倒排扫描过程中,维护标量 Bitset/Bitmap:
探索邻居节点 ──► 检查 Bitset ──┬─► 符合: 加入距离优先队列
└─► 不符: 仅用于图连通跳跃,不计入结果
| 过滤模式 | 执行机制 | 优势 | 风险与工程挑战 |
|---|---|---|---|
| 前过滤(Pre-Filtering) | 借助标量索引先过滤出符合条件的 ID 集合,随后仅在此集合中进行向量搜索 | 绝对满足标量约束条件 | 若筛选后集合过小,在预构建的 HNSW 图上搜索极易陷入不连通的孤岛,导致召回率崩溃 |
| 后过滤(Post-Filtering) | 先通过 ANN 检索召回 Top-$M$ 候选,随后剔除不满足标量条件的项 | 实现简单,完全复用标准 ANN 索引 | 标量过滤选择率极低时,候选集可能被全部剔除,导致无法返回足够的 Top-K 结果 |
| 单遍迭代过滤(Iterative Filtering) | ANN 遍历过程中实时读取标量位图(Bitset),满足标量约束的节点才进入结果队列,其余节点仅作路由跳跃 | 拓扑连通性好,保证召回数量与质量 | 引擎需支持深度耦合的执行内核,标量位图加载带来额外内存访问开销 |
| 分区物理裁剪(Partition Pruning) | 物理上按租户 ID、时间周期将数据切分为独立 Partition/Segment,查询直接路由至对应物理分片 | 彻底消除跨分区无关数据扫描,性能最高 | 依赖清晰的静态分区键,分区过细会导致小文件与调度碎片 |
5.4 复合检索模式扩展
- 范围搜索(Range / Radius Search):检索与查询向量距离小于阈值 $r$ 的所有点。适合高置信度去重或相似度门控,但需设置最大返回条数保护内存;
- 分组聚合搜索(Grouped / Distinct Search):按文档 ID 或商品 SPU 聚合,确保每个主体仅暴露相关度最高的切片,防止单一长文档垄断候选;
- 批量并发搜索(Batch Search):将多个并发 Query 打包为矩阵执行 SIMD/GPU 乘法,提高吞吐量并均摊调度开销;
- 多样性重排(Maximal Marginal Relevance, MMR):在候选相关性与多样性之间权衡,减少返回结果的信息冗余。
5.5 排序流水线与 Cross-Encoder 精排
ANN 阶段为了兼顾吞吐与规模,采用了量化压缩与双塔独立表征,牺牲了部分高精匹配信号。精排流水线负责在小候选集上精细消除误差:
百万级候选集 ──► [ANN 粗召回] ──► 候选 100~200 条 ──► [Cross-Encoder 精排] ──► 最终 Top-K (如 K=10)
(毫秒级) (数十毫秒级)
- 原始浮点重算(Raw Distance Refinement):针对 IVF-PQ 或 DiskANN 产生的候选,从底层存储回读未经量化的 Float32 原向量,重算真实距离,消除量化误差引入的顺序颠倒;
- Cross-Encoder(Reranker 模型)深度重排:
- 双塔模型将 Query 与 Doc 独立编码,无法捕捉词级交叉注意力;
- Cross-Encoder 将 Query 与 Doc 拼接为
[CLS] Query [SEP] Document [SEP]输入单一 Transformer,所有 Token 之间进行完全自注意力交叉比对,输出匹配得分; - 常用开源模型包括
bge-reranker-large、cohere-rerank等。其计算开销随候选数线性增长,工程上候选集规模通常约束在 50~200 个;
- 业务特征加权(LTR / Rule-based Blending):在 Reranker 语义分基础上,线性融合业务时效性衰减(Time-decay)、权威度评分、CTR 预估值及多样性惩罚。
6. 混合检索:稀疏与稠密的互补
6.1 稀疏与稠密检索的互补机制
稠密向量检索(Dense Retrieval)基于深层语义表征,擅长同义改写与泛化语义匹配,但在精确专有名词、产品型号、错误码、缩写及未登录词场景下容易产生虚假匹配(把字面完全不同但相近的概念混淆,产生语义幻觉)。
传统稀疏检索(Sparse Retrieval,如 BM25)与现代学习型稀疏表示基于精确词项倒排,对字面命中极其敏感,但无法处理没有字面重叠的同义表达。
| 检索场景 | 稠密向量(Dense) | 统计稀疏(BM25) | 学习型稀疏(SPLADE) |
|---|---|---|---|
| 同义改写(“密码找回” vs “账号凭证重置”) | 极强(语义空间聚集) | 较差(无字面重叠) | 良好(具备词项扩展能力) |
精确型号/错误码(Error-404-NF, RTX-4090) |
较弱(易被泛化为临近型号) | 极强(倒排唯一命中) | 强(保留精确词项权重) |
| 长尾罕见专有名词 | 依赖模型预训练覆盖度 | 稳定(分词即可索引) | 良好 |
| 长文档跨主题问答 | 受限于 Pooling 平均化稀释 | 依赖词频统计特征 | 良好 |
6.1.1 BM25 算法解析
BM25 是信息检索领域经典的稀疏打分算法:
$$ \operatorname{BM25}(q, D) = \sum_{t \in q} \operatorname{IDF}(t) \cdot \frac{f(t, D) \cdot (k_1 + 1)}{f(t, D) + k_1 \cdot \left(1 - b + b \cdot \frac{|D|}{\text{avgdl}}\right)} $$
- 逆文档频率 $\operatorname{IDF}(t) = \ln\left(\frac{N - n(t) + 0.5}{n(t) + 0.5} + 1\right)$:惩罚语料中的高频常见词(如“的”、“系统”),赋予罕见专业词更高的权重;
- 词频非线性饱和 $\frac{f(t, D) \cdot (k_1 + 1)}{f(t, D) + k_1 \cdot (\dots)}$:$f(t, D)$ 为词项 $t$ 在文档 $D$ 中的出现次数。参数 $k_1$(通常取 $1.2 \sim 2.0$)控制词频增长时的得分增长速度,防止单词简单重复堆砌导致得分无限虚高;
- 文档长度惩罚因子 $1 - b + b \cdot \frac{|D|}{\text{avgdl}}$:$|D| / \text{avgdl}$ 表示文档长度与平均长度的比值。参数 $b$(通常取 $0.75$)用于对长文档进行打折惩罚,消除长文本天然包含更多词项的不公平优势。
6.1.2 学习型稀疏表示(SPLADE)
SPLADE(Sparse Lexical and Expansion Model)利用预训练语言模型预测词表维度的稀疏权重向量:
- 关键词权重预测:模型自动判断文档中哪些词具有核心检索价值;
- 语义词项扩展(Term Expansion):若文档包含“智能手机”,模型可隐式激活词表中未显式出现的“iPhone”或“移动终端”并赋予权重,在倒排索引中实现轻量级语义扩展。
6.2 混合检索系统架构
┌───────────────────┐
│ 用户查询 Query │
└─────────┬─────────┘
│
┌──────────────────┴──────────────────┐
▼ ▼
[稠密通路 Dense Path] [稀疏通路 Sparse Path]
Embedding 模型推理 分词器 Tokenize / 稀疏编码
│ │
ANN 向量索引检索 倒排索引检索 (Inverted Index)
(HNSW / IVF-PQ / DiskANN) (BM25 / SPLADE)
│ │
稠密候选 Top-M1 稀疏候选 Top-M2
└──────────────────┬──────────────────┘
│
▼
[结果融合层 Fusion Layer]
(加权分值融合 / RRF 排名倒数融合)
│
▼
[交叉重排层 Reranker]
(Cross-Encoder 深度打分)
│
▼
最终 Top-K
6.3 结果融合算法(Fusion Strategies)
6.3.1 线性加权分数融合(Score Normalization & Weighted Fusion)
直接将稠密相似度(如余弦值 $[-1, 1]$)与 BM25 分值($[0, +\infty)$)相加会导致数值尺度失衡。需先将各路分值归一化至同一区间:
$$ \widetilde{S}(d) = \frac{S(d) - S_{\min}}{S_{\max} - S_{\min}} \quad (\text{Min-Max 归一化}) $$
$$ \operatorname{Score}{\text{hybrid}}(d) = \alpha \cdot \widetilde{S}{\text{dense}}(d) + (1 - \alpha) \cdot \widetilde{S}_{\text{sparse}}(d) $$
权重系数 $\alpha \in [0, 1]$ 需根据业务类型调整:对于自然语言概念问答可设置 $\alpha = 0.7 \sim 0.8$;对于包含产品型号、代码片段的场景应调整为 $\alpha = 0.3 \sim 0.5$。
6.3.2 倒数排名融合(RRF, Reciprocal Rank Fusion)
RRF 是一种简单实用的多路排名融合算法。它不需要将各路检索的分数做复杂的归一化,直接根据文档在各路中的排名位次计算综合得分:
$$ \operatorname{RRF}(d) = \sum_{m \in \mathcal{M}} \frac{1}{c + \operatorname{rank}_m(d)} $$
- $\mathcal{M}$ 为多路检索通路集合(如 ${\text{Dense}, \text{Sparse}}$);
- $\operatorname{rank}_m(d)$ 为文档 $d$ 在第 $m$ 路召回中的名次(从 1 开始计);
- $c$ 为平滑常数(工业界通常取 $c = 60$),用于降低头部位次差异对最终分数的过度敏感。
RRF 具备高度鲁棒性,不受不同检索器分值分布不均的影响,是生产环境中最常用的默认多路融合方案。
7. 总结
高维向量检索的核心在于依托高质量的数据切分与对比学习 Embedding 建立语义可比的几何空间,并通过 L2 归一化内积计算结合 IVF、PQ、HNSW 或 DiskANN 等 ANN 索引,在召回精度、查询时延与内存硬件成本间取得最佳工程权衡;在实际业务落地中,单纯依赖稠密向量容易在精确型号或专有名词上产生假相关(语义幻觉),必须构建“稠密语义向量 + BM25/SPLADE 稀疏倒排 + 标量条件过滤”的多路召回体系,借助免校准的 RRF 排名融合与 Cross-Encoder 深度精排实现高鲁棒性排序;而生产级向量数据库的核心价值,正在于超越单机算法库,通过 4KB 扇区对齐与数据共置消除 I/O 读放大、异步 io_uring 并发预取、基于标量位图的单遍迭代过滤保持图连通性,以及 WAL 日志、自动分片容灾与模型全生命周期治理,将前沿近邻检索算法安全、弹性、低成本地转化为高可用企业级数据基础设施。