logo蛋烘糕.

不写博客的工程师不是好的产品经理

AI 技术演进与核心算法实战 | 第十一篇:向量数据库内核:HNSW 与 IVF-PQ 近似最近邻搜索算法图解与性能对比

Cover Image for AI 技术演进与核心算法实战 | 第十一篇:向量数据库内核:HNSW 与 IVF-PQ 近似最近邻搜索算法图解与性能对比
蛋烘糕
蛋烘糕

在海量向量中快速找到"最相似"的那个,就像在地球上找离你最近的咖啡店——暴力搜索太慢,我们需要聪明的"导航系统"。

上一篇 中,我们探讨了如何控制大模型的输出格式。现在让我们进入 第三模块:记忆篇 的核心主题 —— 向量检索

想象一下这个场景:你的 RAG 系统有 1000 万份文档,每份文档被编码成 768 维的向量。当用户提问时,你需要在 几毫秒内 从这 1000 万个向量中找到与问题向量最相似的 Top-K 个。

怎么找?暴力搜索吗?

如果逐个计算余弦相似度,假设每次计算需要 1 微秒(这已经很快了),那么:

  • 100 万向量 = 1 秒 ❌(用户早已失去耐心)
  • 1000 万向量 = 10 秒 ❌❌(完全不可接受)
  • 1 亿向量 = 100 秒 ❌❌❌(系统直接崩溃)

这就是为什么我们需要 ANN(Approximate Nearest Neighbor,近似最近邻)搜索算法。

本篇是 《AI 技术演进与核心算法实战》第三模块的第一篇。我们将深入剖析两种最主流的 ANN 算法:HNSWIVF-PQ,通过可视化图解、手写实现和性能对比,让你彻底搞定向量检索的内核。


1. 从"精确"到"近似":为什么我们要学会妥协?

1.1 一个直觉类比:考试选择题 vs 填空题

在做数学题时,老师通常要求精确答案(Exact Match)—— 答案必须是 x=5x=5,不能是 x5x \approx 5

但在生活中,我们更多时候用的是近似思维

  • 朋友问你:“北京哪家川菜馆最好吃?” 你不会把全北京所有餐厅都尝一遍再回答,而是凭经验推荐几家"很可能好吃"的
  • 你在商场找停车位,不会遍历所有车位找"离电梯最近的那个",而是先逛一圈,看到差不多近的就停了

KNN(K-Nearest Neighbors,K 近邻)就是"精确答案":它保证能找到真正的最近邻,但代价是要遍历所有数据点。

ANN(Approximate Nearest Neighbor,近似最近邻)就是"生活智慧":它不保证找到"绝对最近"的,但能保证在可接受的时间内找到"足够近"的。

精确搜索 (KNN) vs 近似搜索 (ANN) KNN:精确但慢 ? 检查所有点 → 保证找到真·最近 时间复杂度:O(N),N 很大时极慢 ANN:快速且够用 ? 智能路径 → 找到"足够近"的解 时间复杂度:O(log N) 或 O(1),快百倍

图解说明:左图展示了 KNN 的做法 —— 以查询点为中心,逐步扩大搜索半径,检查所有数据点,最终找到真正的最近邻(黄色虚线圆)。右图展示了 ANN 的策略 —— 沿着"看起来更近"的方向快速移动,虽然找到的可能不是绝对最近的,但速度提升了几个数量级。

1.2 性能对比:到底能快多少?

下表展示了不同规模下,暴力搜索与 ANN 算法的性能差异:

数据规模 暴力搜索耗时 HNSW 耗时 加速倍数 召回率
1 万向量 10ms 0.5ms 20× 99%
100 万向量 1s 2ms 500× 97%
1000 万向量 10s 5ms 2000× 95%
1 亿向量 100s 10ms 10000× 93%

关键洞察:ANN 用 1-7% 的精度损失,换取了 数百到数万倍的速度提升。这在工程上是极其划算的交易!


2. HNSW 算法:像"搭电梯"一样搜索向量

2.1 一个绝妙的直觉类比:摩天大楼找楼层

想象你要在一栋 100 层的摩天大楼 里找一个人,他的办公室在"第 73 层"。你怎么找最快?

暴力搜索的做法:从 1 楼开始,逐层敲门询问:“他在这里吗?” —— 这要敲 73 次门。

HNSW 的做法

  1. 跳到空中花园(顶层高速路):你先坐电梯到 100 层的空中连廊,这里可以俯瞰整栋楼。
  2. 快速定位大致区域:从高空往下看,你发现 73 层大概在中间偏上的位置。
  3. 逐层下降:你走楼梯下到 80 层,再下到 75 层,最后到 73 层。
  4. 找到目标:在 73 层挨个房间找,很快就找到了。

HNSW(Hierarchical Navigable Small World,分层可导航小世界) 的核心思想就是这个"空中连廊 + 逐层下降"的策略!

HNSW 分层搜索过程:从"高速路"到"本地街道" L3 (顶层) 高速连接(长距离跳跃) L2 (中层) 中等距离连接 L1 (底层 - 原始数据) 入口 目标 搜索路径: 1. 顶层快速定位 2. 中层缩小范围 3. 底层精细搜索

图解说明:上图展示了 HNSW 的三层结构。顶层(L3) 节点稀疏但连接距离远,像"高速公路";中层(L2) 节点密度中等,连接距离适中;底层(L1) 包含所有数据点,连接都是"本地街道"。搜索时从顶层入口开始,沿着橙色路径逐层下降,最终在底层找到目标。这种策略使得搜索复杂度从 O(N) 降到了 O(log N)。


3. IVF-PQ 算法:先"分班级"再"压缩存储"

3.1 一个直觉类比:图书馆找书

假设你是图书馆管理员,要在 100 万本书 中找"跟《哈利波特》最相似的 10 本书"。你怎么找?

暴力搜索:把 100 万本书全部拿下来,一本本比较 —— 累死也找不到。

IVF-PQ 的做法

  1. 分班级(Inverted File,倒排索引)

    • 先把书按照"奇幻文学"、“科幻小说”、"历史传记"等分类。
    • 《哈利波特》属于"奇幻文学"类,这个类别有 5 万本书。
    • 搜索范围瞬间从 100 万缩小到 5 万!
  2. 压缩存储(Product Quantization,乘积量化)

    • 每本书的特征向量有 768 维,直接比较太慢。
    • PQ 把 768 维拆成 8 段,每段 96 维。
    • 对每一段进行聚类(比如聚成 256 类),用聚类中心的编号(0-255,只需 1 字节)代替原始向量。
    • 768 维 × 4 字节 = 3072 字节 → 8 字节!压缩了 384 倍!
  3. 粗检索 + 精排序

    • 先用压缩后的向量快速筛选出前 100 个候选。
    • 再用原始向量对这 100 个候选做精确排序。
    • 既快又准!
IVF-PQ 两阶段:倒排索引 + 乘积量化 Step 1: IVF 倒排索引(分班级) 奇幻类 中心 科幻类 历史类 100 万向量 → K 个聚类(如 K=1000) Step 2: PQ 乘积量化(压缩) 原始向量:768 维 [0.23, 0.56, ..., 0.89] (3072 字节) ... 子向量 1 子向量 2 子向量 3 子向量 8 #157 #89 #203 ... #42 压缩后:[157, 89, 203, ..., 42] (仅 8 字节!) 每个子向量用聚类中心编号表示

图解说明:左图展示了 IVF 的聚类过程 —— 将 100 万个向量分成 K 个簇(如 K=1000),每个簇有一个聚类中心(红色圆点)。查询时先找到最近的几个簇,只在簇内搜索,大幅减少候选数量。右图展示了 PQ 的压缩过程 —— 将 768 维向量切成 8 段,每段独立聚类(如 256 类),用聚类中心的编号(0-255,1 字节)代替原始向量,实现 384 倍压缩。


4. HNSW vs IVF-PQ:终极性能对比

4.1 理论对比表

特性 HNSW IVF-PQ
数据结构 多层图结构 倒排索引 + 压缩编码
搜索复杂度 O(log N) O(√N)(理想情况)
内存占用 高(需存储图结构) 极低(压缩 32-128 倍)
构建速度 中等 快(KMeans 可并行)
查询延迟 极低(微秒级) 低(毫秒级)
召回率@10 95-99% 90-95%
适合场景 实时检索、低延迟要求 海量数据、内存受限
参数调优 M, ef_construction, ef_search nlist, m, nbits, nprobe

4.2 选型建议

选择 HNSW,如果你需要

  • 极致查询性能:要求亚毫秒级延迟
  • 高召回率:不能容忍精度损失
  • 实时更新:频繁插入/删除向量
  • 中小规模:数据量 < 1 亿

选择 IVF-PQ,如果你需要

  • 海量数据存储:数据量 > 1 亿甚至数十亿
  • 内存受限:需要在有限内存中容纳更多向量
  • 批量查询:可以接受稍高的延迟换取吞吐量
  • 离线场景:数据相对静态,不频繁更新

4.3 主流向量数据库的实现策略

有趣的是,现代向量数据库通常同时支持两种算法

数据库 HNSW 实现 IVF-PQ 实现 混合策略
Milvus ✅ 支持 ✅ 支持 根据数据量自动选择
Weaviate ✅ 主打 HNSW 纯 HNSW 优化
Qdrant ✅ 自研 HNSW HNSW + 量化压缩
Faiss ✅ 支持 ✅ 最强实现 提供 20+ 种索引类型
Chroma ✅ HNSW 轻量级 HNSW

最佳实践

  • 小规模(<100 万):无脑 HNSW,参数 M=16, ef_search=50
  • 中规模(100 万 -1000 万):HNSW 或 IVF-PQ 均可,看延迟要求
  • 大规模(>1 亿):IVF-PQ 为主,或 HNSW+PQ 混合(如 HNSW 做粗排,PQ 做精排)

5. 总结

在这篇文章中,我们深入探讨了两种最主流的 ANN 算法:

  1. HNSW(分层可导航小世界)

    • 核心思想:像"搭电梯"一样,从高层高速路逐层下降到底层本地街道
    • 优势:查询速度极快(微秒级),召回率高(95-99%)
    • 代价:内存占用大,构建速度中等
    • 适用场景:实时检索、低延迟要求、中小规模数据
  2. IVF-PQ(倒排文件 + 乘积量化)

    • 核心思想:先"分班级"缩小搜索范围,再"压缩存储"提升计算效率
    • 优势:内存占用极低(压缩 32-128 倍),适合海量数据
    • 代价:召回率稍低(90-95%),有损压缩
    • 适用场景:十亿级向量、内存受限、批量查询
  3. 工程实践中的权衡

    • 没有银弹:根据数据规模、延迟要求、内存限制选择合适的算法
    • 混合趋势:现代数据库倾向于同时支持多种索引,动态选择最优方案
    • 参数调优:理解每个参数的物理意义,通过实验找到最佳平衡点

5.1 动手实验建议

为了真正掌握这两种算法,我建议你:

  1. 使用 Faiss 库实战

    pip install faiss-cpu
    
  2. 在真实数据集上测试

    • 下载 SIFT1M 或 GloVe 向量数据集
    • 分别用 HNSW 和 IVF-PQ 构建索引
    • 对比查询延迟、召回率、内存占用
  3. 调参实验

    • 改变 HNSW 的 M 和 ef_search
    • 改变 IVF-PQ 的 nlist 和 nprobe
    • 绘制"延迟 - 召回率"曲线,找到最优参数

📚 参考文献与延伸阅读

  1. Efficient and Robust Approximate Nearest Neighbor Search Using Hierarchical Navigable Small World Graphs (Malkov & Yashunin, 2018)

  2. Billion-scale similarity search with GPUs (Johnson et al., 2019)

  3. Product Quantization for Nearest Neighbor Search (Jégou et al., 2011)

  4. Faiss GitHub Repository

  5. Milvus Vector Database Documentation

  6. Approximate Nearest Neighbor Search Survey (Indyk & Motwani, 1998)

  7. Visualizing HNSW Graphs (博客)

  8. RAG 向量检索系统实战教程


下一篇预告数据流水线工程:非结构化文档的清洗、分块(Chunking)策略与元数据管理 —— 理解了如何快速检索向量后,我们将在下篇探讨如何准备高质量的向量数据,包括文档清洗、智能分块、元数据设计等工程实践。敬请期待!

博客日历
2026年04月
SuMoTuWeThFrSa
29
30
31
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
01
02
03
04
05
06
07
08
09
更多
--
--
--
--