索引选不对,成本贵十倍!HNSW与IVF如何做选型

在向量数据库中,我们经常需要在海量高维向量(例如图像特征、文本 Embedding、语音向量)里快速找到最相似的若干个结果。如果没有索引,就只能逐个查询向量和底库向量的计算相似度,这就叫暴力搜索 (brute force),当数据量达到千万、亿级时,暴搜几乎不可用。
为了解决大规模向量检索效率问题,研究者提出了近似最近邻搜索(ANN, Approximate Nearest Neighbor Search) 方法,其中,最经典的一种索引算法就是 IVF(Inverted File)倒排文件索引。
1. 什么是 IVF 向量索引?
IVF(Inverted File,倒排文件)向量索引,是近似最近邻(ANN)搜索算法中的一种,核心是借鉴文本检索的 “倒排索引” 思路。
它通过“聚类”把高维向量空间划分成若干个簇(bucket),每个簇由一个中心向量(centroid)和属于该簇的向量列表组成。
基于这一分类,查询会被分为两个步骤:
定位 “临近簇”:先找到离查询向量最近的几个簇,排除绝大多数无关向量;
簇内精算:只在这几个簇里做精确距离计算,不用遍历全库。
靠先筛选、再细算,IVF 把高维向量搜索的计算量砍了大半。其过程就像一座高效图书馆。所有书籍(向量)按类别(簇)分好区,比如人文、历史、科技;读者(查询向量)进门不用瞎转,直接锁定最相关的 2-3 个区域,在小范围里找书,效率自然翻倍。
2. IVF 向量索引构建流程(Build)
IVF 索引的构建过程可以分为三个主要阶段:聚类训练、向量分配和向量压缩编码(可选),整体的构建流程如下图所示:
28-1.webp
Step 1. 训练质心(Centroids)
首先,对数据集 X 运行 k-means 聚类,将高维向量空间划分为 nlist 个簇(cluster)。每个簇有一个代表点(质心 centroid),存放在质心表 C 中。质心数量 nlist 是一个关键超参数,决定了簇划分的粒度。
k-means 的原理:
初始化:随机选择 nlist 个向量作为初始质心。
分配样本:计算每条向量到所有质心的距离,把它分配到最近的簇。
更新质心:对每个簇,计算簇内向量的平均值作为新的质心。
迭代收敛:重复分配和更新,直到质心位置基本稳定或达到最大迭代次数。
最终得到的 nlist 个质心,就构成了 IVF 的“索引目录”。这些质心决定了数据的“粗分桶”方式,后续查询时会先用它们来快速缩小搜索范围。训练质心这一步类比图书馆区域分类:nlist 越大,类别分得越细;nlist 越小,每个类别越“大杂烩”。
Step 2. 建立倒排表(Inverted Lists)
每条向量根据“距离哪个质心最近”被分配到对应簇,形成倒排表 List_i。
倒排表记录了属于该簇的所有向量 ID 及其存储信息。
收益:查询时不必遍历全库,而是只看几个最相关的 List。
建立倒排表这一步类比书本被分配到对应主题区域,借书时只查相关区域,不用逛全馆。
Step 3. 向量压缩编码(可选)
为了节省内存和加速计算,常常对簇内向量做压缩编码,常见的压缩编码方式有:
SQ8(Scalar Quantization):对向量的每个维度做 8bit 标量量化,对于 float32 的向量,存储空间从 4 字节压缩为 1 字节,实现4:1的压缩比。
PQ(Product Quantization):对簇内向量做乘积量化,将高维向量拆分成若干个子空间(例如把 128 维拆成 8 个子向量,每个 16 维)。在每个子空间里,预先训练一个小码本(通常大小为 256),用一个 8 bit 索引来表示该子向量的近似位置。这样,一个 128 维的原始向量(float32 存储需 512 byte),最终只需要 8 个byte(8 个子空间 × 1 byte)就能表示,实现了约 64:1 的压缩比。
当然不对簇内向量进行压缩也是可以的,就是常见的 IVF_FLAT 索引。
通过前面三步的构建,最终生成的 IVF 索引包含三部分:
质心表 C:存放所有簇的代表向量(中心点向量)。
倒排表 Lists:每个簇里的成员 ID 与编码。
编码器及码本(可选):用于存储向量的压缩表示,并通过查表的方式加速近似距离计算。
3. IVF 向量索引查询流程(Search)
有了前面构建好的 质心表 + 倒排表 + 编码器及码本(可选),查询时就可以利用 IVF 索引来加速相似向量搜索。搜索过程可以分为三步,如下图所示:
28-2.webp
Step 1. 计算查询向量到所有质心的距离
当一个查询向量 q 到来时,首先需要判断它最可能属于哪些簇。
系统会将 q 与质心表 C 中的所有质心计算距离(通常用欧式距离或内积)。
然后对这些质心按距离进行排序,得到一个由近到远的簇列表。
例如,图中显示的排序结果是:C4 < C2 < C1 < C3 < C5。
Step 2. 选择距离最近的 nprobe 个簇
为了避免全表扫描,IVF 只会在 前 nprobe 个最近的簇中继续检索。
参数 nprobe 控制了搜索范围:
nprobe 越小,速度快但召回率降低;
nprobe 越大,召回率更高但延迟上升。
实际应用中,可以根据延迟预算来动态调整 nprobe。
在图例中,nprobe = 2,因此只会选择 Cluster 2 和 Cluster 4 作为候选簇。
Step 3. 在候选簇内进行精确或近似比较
进入候选簇后,就需要比较查询向量与簇内向量的相似度:
精确比较(IVF_FLAT):直接取出原始向量,与 q 逐个计算距离,得到最准确的结果。
近似比较(IVF_PQ/IVF_SQ8):如果采用了 PQ/SQ8 压缩,如果采用了 PQ/SQ8 压缩,系统会用查表法(lookup table method) 来加速距离计算:在查询开始时,预先计算查询向量与码本的距离,之后只需“查表+加和”即可快速得到近似距离。
最终,来自不同簇的候选结果会被合并排序,输出最相似的 Top-k 向量。
4. 最佳实践
在理解了 IVF 向量索引的构建与搜索流程之后,真正落地到业务时,往往还需要在 性能、精度和内存 三者之间做权衡。下面结合工程实践,给出一些常见的经验指导。
4.1 nlist 的选择
nlist 越大:簇划分越细,每个簇更小,搜索时需要扫描的向量更少,速度更快。但代价是索引构建更慢,而且质心表(centroids)占用更多内存。
nlist 越小:构建快,但每个簇更“拥挤”,检索时单簇扫描量更大,容易出现性能瓶颈。
经验值:对于百万级数据,通常设定
nlist ≈ √N(N 代表需要创建索引的数据分片中的向量条数)是一个不错的起点。例如 100 万向量,可以选 nlist=1000;对于更大的数据量,千万级或者亿级,在常见的向量数据库系统中,一般都会对数据进行分片,使每个分片的数据量在百万级。因为是创建索引时的参数,设置的时候需要更加谨慎,后期想要修改时,需要重新对数据集构建索引。建议在实际业务中,按照2的指数幂,比如 1024,2048 多测试几组。
4.2 nprobe 的调优
nprobe 越大:覆盖的簇越多,召回率越高,但延迟也会线性上升。
nprobe 越小:延迟很低,但可能漏掉一些真正的近邻,影响结果质量。
调参建议:在延迟不敏感的情况下,可以动态调整 nprobe(比如从 1–16 逐步试探),观察召回率和延迟曲线,找到“平衡点”。因为是搜索端的参数,可以随时进行调整,修改的代价很低。
4.3 IVF 索引的常见变体
在构建索引过程中,是否对簇内向量做压缩编码,以及使用哪种压缩编码方式,可以派生出 IVF 索引的三种常见变体:
| IVF 变体 | 特点 | 适用场景 |
|---|---|---|
| IVF_Flat | 簇内原样存储向量,无压缩,精度最高,内存占用最大 | 数据量中等(亿级以内)场景、召回率要求高(95%+) |
| IVF_PQ | 簇内向量用乘积量化(PQ)压缩,通过调节压缩比,可使内存大幅下降 | 亿级以上的大规模向量检索,可接受精度损失,64:1压缩后,recall 通常在 70% 左右,不过通过减小压缩比,也可以提升整体recall到90%+ |
| IVF_SQ8 | 采用标量量化,内存占用介于 Flat 与 PQ 之间 | 亿级以上大规模检索,且需要保证较高精度(recall 90%+) |
28-3.webp
4.4 与 HNSW 的对比
IVF 和 HNSW(分层可导航小世界) 都是常见的内存型向量索引,下面通过一张对照表来详细了解两者的区别。
| 维度 | IVF(倒排文件) | HNSW(分层可导航小世界) |
|---|---|---|
| 算法思想 | 聚类分桶 | 多层图导航 |
| 内存占用 | 较低 | 较高 |
| 索引构建速度 | 快(只需聚类) | 慢(需建多层图) |
| 查询速度(无过滤) | 快,依赖 nprobe | 极快,对数级复杂度 |
| 查询速度(带过滤) | 快, 质心层面先筛选簇缩小范围 | 不稳定,尤其是过滤比例较高( 90%+)时,几乎全图上做遍历,比暴搜还慢 |
| 召回率 | 与是否量化有关,非量化情况召回率可达95%以上 | 通常更高,98%以上 |
| 参数 | nlist、nprobe | m、ef_construction、ef_search |
| 适用场景 | 内存有限且需较高查询性能和召回率,带过滤条件的检索 | 内存充足且需极高查询性能和召回率,无过滤或过滤比例不高 |
28-4.webp
在实际应用中,过滤条件( “只查某个用户的数据” 或 “限定时间区间内的向量”)非常常见。但是由于算法原理的区别,IVF 比 HNSW 更擅长处理过滤搜索。
IVF 优势:IVF 可以先在簇质心层面粗过滤,快速缩小候选集合,再做向量级别的精确比对,因此即便过滤比例很高,性能依旧可控。
HNSW 劣势:HNSW 是基于图遍历的搜索,无法在结构层面直接利用过滤条件。当过滤比例低时影响不大,但如果过滤比例很高(比如 90%+ 的数据被过滤掉),会使得图里的数据形成很多孤岛,就可能导致几乎在全图上做遍历,性能比暴力搜索还差。
5. 总结
IVF(Inverted File Index,倒排文件索引)作为向量数据库中最经典的近似最近邻(ANN)方法之一,已经在工业界和学术界得到了广泛应用。它的核心思路是“先粗分,再细排”:通过 k-means 聚类将海量高维向量划分到不同簇中,查询时只需进入最相关的少量候选簇,既避免了全表暴力扫描,又能兼顾速度与精度。通过调节 nlist 与 nprobe,用户可以在不同场景下灵活权衡延迟与召回率。在实际落地中,IVF 索引已经被应用在多类高价值场景:
电商搜索:用户根据一张商品图片,快速在海量底库中找到相似商品。
专利检索:通过一段描述,在亿级专利库中找到语义最相关的专利,比传统关键词搜索更高效。
RAG 知识库:根据用户问题,在百万级租户数据中,找出精准的上下文内容。
与 HNSW 等图索引相比,IVF 的优势在于构建速度快、内存消耗低,尤其适合大规模和带过滤条件的检索。在工程实践层面,Milvus 等开源向量数据库已经对 IVF 全系列索引做了完整支持,开发者可以直接调用 IVF_FLAT、IVF_PQ、IVF_SQ8 等索引类型。如果你正在探索如何落地图片搜索、推荐系统或RAG知识库等AI应用,不妨尝试在 Milvus 中体验 IVF 索引,感受高效的向量搜索能力。

技术干货
LLM 快人一步的秘籍 —— Zilliz Cloud,热门功能详解来啦!
此次我们在进行版本更新的同时,也增加了多项新功能。其中,数据迁移(Migration from Milvus)、数据的备份和恢复(Backup and Restore)得到了很多用户的关注。本文将从操作和设计思路的层面出发,带你逐一拆解 Zilliz Cloud 的【热门功能】。
2023-4-10
技术干货
如何设计一个面向开发者全生命周期成本的全托管向量检索服务产品?
作为产品的设计者和开发者,必须始终以用户为中心,积极倾听他们的需求,并集中精力降低软件开发的全链路成本,而非过度追求极致性能或过分炫技。在这种背景下,降低开发者的综合使用成本已成为 Zilliz Cloud 和开发团队过去的主要使命。
2023-7-5
技术干货
门槛一降再降,易用性大幅提升!Milvus 2.2.12 持续升级中
一句话总结 Milvus 2.2.12 :低门槛、高可用、强性能。
2023-7-27




