免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

向量检索索引算法深度拆解:HNSW、IVF、DiskANN到底怎么选?

向量检索索引算法深度拆解:HNSW、IVF、DiskANN到底怎么选? 导读向量检索领域HNSW、IVF、DiskANN三种索引方案各有千秋但面对数据量、延迟、召回率、内存等不同需求到底该如何选择本次尝试拆解三种索引的底层逻辑、核心公式和关键参数提供选型建议。你刚上线一个向量检索服务。10万条向量768维HNSW索引QPS打到5000P99延迟3ms召回率96%。一切看起来很美。数据涨到500万。内存突然吃掉60GB延迟飙到50msQPS掉到800。你慌了于是你开始思考是不是索引的问题。01 暴力检索的O(N) 困境先说为什么需要索引。向量检索的本质是给定一个查询向量q在N个候选向量中找出距离q最近的K个。最直接的做法——把所有向量的距离算一遍排序取TopK。这是我们常说的暴力检索Flat索引。暴力检索的复杂度是O(N×d)N是向量数量d是维度。10万条768维向量每次查询7680万次浮点运算——GPU 随便跑CPU 也只要几毫秒。但N涨到1000万呢768亿次运算单次查询几十毫秒起步。如果你做的是实时推荐或RAG这个延迟基本不可用。核心问题变成了怎么在牺牲一点点精度的前提下把O(N) 干到O(logN) 甚至更低目前主流方案走了三条路用图结构、用空间分区、用磁盘内存混合。对应的就是HNSW、IVF、DiskANN。02 三条路线的根本分歧在看具体算法之前先理解这三条路线的底层逻辑差异。图路线HNSW的思路建一张图每个节点是一个向量相连的节点是空间上的近邻。查询时不需要遍历所有节点从图的入口出发沿着边贪心地向目标方向移动几跳就能到达近邻区域。本质上是用预计算的近邻关系替代实时距离计算。分区路线IVF的思路把向量空间切成一堆区域用K-means聚类每个区域有个中心点。查询时先找最近的几个中心点只在这几个区域内做暴力检索。本质上是用空间分治减少需要计算距离的候选数量。磁盘路线DiskANN的思路HNSW的图太占内存1000万条768维向量原始向量数据就要几十GB。能不能把图和全精度向量放SSD上内存里只放压缩后的向量做初步筛选本质上是用分级存储解决图索引内存爆炸的问题。三条路线的取舍点完全不同。下面逐个看下。03 HNSW用分层图做先粗后细核心结构HNSW的全称是Hierarchical Navigable Small World。拆开看三个词Hierarchical分层图分多层。最顶层只有少数节点边很长远距离连接最底层包含所有节点边很短近距离连接。这个结构灵感来自跳表Skip List。Navigable可导航从任意节点出发都能通过有限的跳数到达任意其他节点。这要求每个节点的连接数不能太少。Small World小世界网络同时具备近距离邻居多和远距离捷径存在的特性使得平均最短路径长度是O(logN) 级别的。算法公式。先把距离定义说清楚。向量检索最常用的距离度量是欧氏距离和余弦相似度余弦相似度取值 [-1, 1]值越大越相似。转成距离就是 1- sim(q, v)。层级分配。HNSW的层次结构靠一个随机层级函数决定每个节点能爬到第几层其中 m_L 是层数归一化因子通常取 1/ln(M)。这个公式让高层节点呈指数级稀疏——如果M16大约1/16的节点在layer≥11/256的节点在layer≥2以此类推。顶层只有极少几个节点充当整个图的高速公路入口。查询算法。分层贪心搜索的核心逻辑SEARCH-LAYER(q, ep, ef, lc): v ← ep // 当前层的入口点 C ← {ep} // 候选集 W ← {ep} // 结果集 (动态维护最近的 ef 个节点) while C 非空: c ← C 中距离 q 最近的节点从 C 中移除 f ← W 中距离 q 最远的节点 if dist(c, q) dist(f, q): break // 所有剩余候选都不如当前最差结果提前终止 for each e in c 在第 lc 层的邻居: if e 未被访问: 将 e 加入 C 和 W 如果 |W| ef, 移除 W 中最远的节点 return W完整的多层搜索从最高层开始逐层下降每一层的终点作为下一层的入口K-ANNSearch(q, K, ef): for l topLevel down to 1: ep SEARCH-LAYER(q, ep, 1, l) // 高层 ef1快速定位 ep SEARCH-LAYER(q, ep, ef, 0) // 底层用完整 ef 精细搜索 return K nearest from ep注意一个细节在第l≥1层搜索时ef1就够了——高层的目的是快速定位到近邻区域不需要高精度。只有最底层l0才用完整的ef_search做精细搜索。建图时的邻居选择。插入新节点时HNSW不会把所有近邻都连上而是用一个启发式剪枝策略保证图的质量SELECT-NEIGHBORS(q, C, M): 从C中选出距离q最近的节点e1加入结果集R for each e in C \ R: if dist(q, e) dist(e, nearest in R): 将 e 加入 R if |R| M: break return R这个策略的核心作用是如果一个候选点已经在结果集中某点的势力范围内就不需要再连它了。结果是图中的边分布更均匀避免在密集区域形成冗余连接。直观理解整个搜索过程就像找一家餐厅——先看全国地图锁定城市高层再看城市地图锁定街区中层最后在街区里逐家比较底层。每一层的粒度不同高层负责快速定位大区域底层负责精确匹配。三个关键参数HNSW有三个参数直接决定性能表现M每个节点的最大连接数。M越大图的连通性越好召回率越高但内存也越大。常用值16-48。在1000万条768维向量的场景下M16时图结构大约10GB加上原始向量30GB总共40GB。M32会再多吃5-8GB。ef_construction建图时候选集大小。越大建图质量越好但建图时间越长。一般取200-500。这个参数只在建索引时起作用建好后改不了。ef_search查询时候选集大小。这是唯一一个可以在运行时动态调整的参数。ef_search越大召回率越高延迟也越高。典型的权衡曲线是这样的ef_search从50提到200召回率从88% 升到97%但P99延迟从2ms升到8ms。一个容易被忽略的点M和ef_construction在建索引时就定死了之后想改只能重建。所以建索引之前要想清楚数据规模和精度要求。ef_search可以随时调线上A/B测试很方便。在10M级别、1024维的基准测试中HNSWM32, ef_search128能拿到95-98% 的Recall10P99延迟5-15ms内存约12GB含原始向量与图结构。但当数据量膨胀到10亿级别SIFT-1B数据集即使采用M16的保守配置仅图结构就需要占用数百GB内存加上原始向量数据总内存消耗轻松突破**TB级别**这也是HNSW的天花板。优缺点优点明显查询速度快O(logN) 级别的跳数召回率高ef_search调大可以到99%支持增量插入不需要重建索引就能加新数据。缺点也明显内存占用大图结构本身N×M×4字节加上原始向量N×d×4字节总内存约原始数据的1.5倍建索引慢1000万条向量建HNSW索引单机要好几个小时10亿级别要18小时以上不支持高效删除删除节点会破坏图结构通常用标记删除 定期重建。总之HNSW用内存换速度适合数据量在内存装得下、对延迟和召回都有高要求的场景。04 IVF用聚类做空间分治核心结构IVFInverted File Index的思路更直觉先把向量空间分成nlist个区域每个区域有个中心点centroid。所有向量归到距离自己最近的中心点。查询时先算查询向量到所有中心点的距离选出最近的nprobe个区域只在这些区域内做暴力检索。算法公式。IVF的第一步是训练聚类中心。用K-means最小化每个向量到所属中心的距离平方和训练收敛后得到 nlist 个中心点 {μ₁, μ₂, …, μ_nlist}。每个向量v被分配到距离最近的中心每个中心维护一个倒排列表inverted list记录归属于它的所有向量ID。查询过程分两步计算查询向量q到所有中心点的距离选出nprobe个最近的中心只在这些中心对应的倒排列表中做暴力检索PQ压缩IVF-PQ的核心。PQ不直接把向量做整体量化而是切成m段子向量每段独立量化。对768维向量切成96段每段8维对每一段训练一个256码字的码本K-meansk256把8维浮点向量映射到1字节的码字索引编码后整个向量变成96字节从3072字节压缩32倍。查询时距离也分段近似计算关键优化查询向量的q^(j) 到该段所有256个码字的距离可以预计算成一张96×256的查找表。实际检索时只需要查表累加——96次查表 95次加法比浮点向量计算快两个数量级。直观理解这就像图书馆的分类系统——先看你要的书属于哪个大类计算机、文学、历史然后只去对应的几个书架找不用翻遍整个图书馆。nprobe就是你去几个书架——去1个书架最快但可能漏掉去所有书架就是暴力检索了。IVF-Flat vs IVF-PQIVF有两种变体区别在于区域内怎么存向量IVF-Flat区域内存原始向量。检索时用暴力计算精确距离。精度高但内存占用大O(N×d)。1000万条768维向量原始数据就要30GB每个维度存一个 float32每条向量768 × 4 3072 字节 ≈ 3KB1000万条10,000,000 × 3072 30,720,000,000 字节二进制算≈ 28.6GB。IVF-PQ区域内存压缩后的向量。PQProduct Quantization把d维向量切成m段每段用256个码字做量化。768维向量切成96段每段8维每段用1字节存储整个向量从3072字节压到96字节——32倍压缩。检索时用压缩向量算近似距离精度有损但内存大幅降低。代价是什么PQ压缩会引入量化误差。768维向量压到96字节召回率大概会掉5-15个百分点取决于数据和参数。但如果你有1000万条向量内存预算只有10GBIVF-PQ可能是唯一能跑起来的方案。在10M级别基准测试中IVF-Flatnlist65536, nprobe64的Recall10约91.5%QPS约120把nprobe提到256Recall升到96.8%但QPS掉到45。对比同级别的HNSW98.2% Recall, 450 QPSIVF-Flat在召回和吞吐上都有差距但内存只有HNSW的60-70%。两个关键参数nlist聚类中心数量。一般取N的平方根到4倍平方根。1000万条向量nlist取3000-12000。nlist太小每个区域内向量太多暴力检索慢nlist太大找中心点本身就要算很多次距离而且每个区域内向量太少召回率下降。nprobe查询时搜索的区域数量。这是IVF的核心调参旋钮。nprobe1只搜最近的1个区域速度最快但召回最低nprobenlist等于暴力检索召回100% 但失去加速意义。典型设置nprobe8-32可以在召回率90% 和10ms以内延迟之间取得平衡。IVF的优势在于灵活——nprobe可以运行时动态调整不像HNSW的M和ef_construction建好就定死了。线上流量高峰时调低nprobe保延迟流量低谷时调高nprobe补召回。优缺点优点内存可控IVF-PQ可以大幅压缩建索引快K-means聚类比HNSW建图快一个数量级10亿级数据IVF约4小时vs HNSW 18小时支持GPU加速Faiss的GPU-IVF是经典方案。缺点召回率天花板低于HNSWIVF-PQ有量化损失高维数据上聚类效果会变差维度灾难导致K-means中心点区分度下降对数据分布敏感如果聚类中心选得不好某些区域向量过多导致长尾延迟。一句话总结IVF用精度换内存适合数据量大但内存预算有限的场景。05 DiskANN当图放不进内存为什么需要DiskANNHNSW的图索引性能很好但有个硬伤内存。1000万条768维向量的HNSW索引M16图结构大约10GB加上原始向量30GB总共40GB。这个数字在百万级数据量下还OK但上亿条向量呢400GB内存绝大多数机器扛不住。有人可能会说加机器不就行了分片sharding确实可以解决但每加一台机器就多一份运维成本和故障点。而且分片后的跨节点查询延迟会显著上升。DiskANN就是来解决这个问题的——让图索引在图放不进内存的情况下依然能高效查询。微软在2019年NeurIPS上发表了这篇论文到2026年3月已经更新到v0.49.1Rust重写版支撑着Bing、Microsoft 365和Azure Cosmos DB的向量检索。核心结构DiskANN的关键思路是分级存储内存里放压缩后的向量PQ编码用于快速计算近似距离做初步筛选。1000万条768维向量PQ压缩后大约1GB。SSD上放全精度向量和图的邻接表用于精确计算和图遍历。同样是1000万条768维向量SSD上大约30GB。查询过程分两步从入口节点出发用内存中的PQ编码算近似距离在图上做贪心导航选出一批候选节点。这一步完全不读磁盘。把候选节点的全精度向量从SSD读到内存用全精度向量重新算精确距离做最终排序。算法公式Beam Search磁盘友好的图搜索。DiskANN的查询核心是beam search——并非像HNSW那样逐个节点贪心跳转而是一轮一轮地扩展候选集BEAM-SEARCH(q, start, W, L): B {start} // beam每轮维护的活跃候选集 V {start} // 所有已访问节点 while B \ V 非空: // 有新节点可扩展 N ∪ neighbors(v) // 批量获取邻居SSD 预取 V B // 标记本轮节点为已扩展 B TopK_W(V ∪ N, dist_PQ) // 用 PQ 近似距离选 topW return TopK_L(V, dist_exact) // 最终用精确距离重排关键参数W控制beam宽度——W越大搜索越彻底召回越高但每轮要评估的候选也更多。L是最终返回的候选数L ≥ K一般取K的几倍以获得更好的重排质量。这里有一个细微但重要的点beam search在扩展阶段用的是PQ近似距离dist_PQ只在最终重排时才读SSD做精确距离计算dist_exact。这样做的理由很直白——扩展阶段要评估大量节点如果每次都读SSD延迟直接爆炸。先在内存用近似距离筛出小范围候选再精准打击I/O量降了1-2个数量级。Vamana图构建算法。Vamana图和HNSW图的关键区别在建图时的剪枝策略——RobustPruneROBUST-PRUNE(p, V, α, R): V ← V ∪ {p} for v in V \ {p}: if α · ‖p - v‖ ≤ dist(v, nearest in N_out(p)): 将 v 加入 N_out(p) if |N_out(p)| R: break return N_out(p)参数 α 是Vamana的灵魂。α ≥ 1控制对长边的容忍度α 1严格保留最近邻图变成稠密的局部近邻图。查询时要走很多步。α 1.5~2.0允许保留一些不算最近但也不远的节点作为长距离捷径。图的直径变小跳数减少。α 太大边太多内存和建图时间都扛不住。HNSW用多层结构实现先粗后细Vamana用 α 参数在单层图中嵌入长距离捷径。前者优雅但依赖分层带来的额外随机读后者粗暴但单层图的SSD批量预取效率更高。在SIFT-1B数据集10亿条128维向量上DiskANN在64GB内存 NVMe SSD的单机上实现了95% recall1平均延迟低于5msQPS约5000。同样的数据量HNSW需要数百GB内存才能达到类似性能。Vamana图vs HNSW图DiskANN用的不是HNSW的多层图而是一种叫Vamana的单层图。区别在于HNSW靠多层结构实现先粗后细的快速定位。Vamana没有分层但通过一个alpha参数控制边的剪枝程度——alpha越大保留越多的长距离边图的导航性越好但建图时间也越长。为什么不直接用HNSW的多层结构存磁盘因为HNSW的多层结构需要从顶层开始搜索每层之间的切换会引入额外的随机读。在内存里这不是问题但在SSD上每次随机读都是100微秒的代价。Vamana的单层结构虽然搜索时跳数更多但每次跳转都是一次SSD读可以用beam search批量预取反而比多层结构更适合磁盘场景。FreshDiskANN支持实时更新原始的Vamana图是静态的——建好之后不能加新数据。微软后来推出了FreshDiskANN支持并发的实时插入、删除和更新不需要全量重建索引。这让DiskANN能用于推荐系统、实时文档检索这类数据持续增长的场景召回率保持在95% 以上。优缺点优点内存占用极小只需要PQ编码1000万条向量大约1GB内存可以支撑十亿级向量SSD够大就行召回率接近HNSW90-95%。缺点查询延迟比HNSW高一个数量级10亿级5ms vs 百万级亚毫秒SSD I/O是瓶颈建索引依赖大量SSD读写冷启动较慢。总之DiskANN用延迟换内存适合数据量大到HNSW放不进内存的场景。06 怎么选一个决策框架讲了这么多原理和参数落到实际选型上核心就五个问题维度HNSWIVF-FlatIVF-PQDiskANN适用数据量百万~5000万百万~千万千万~亿亿~百亿P99 延迟1~15ms5~30ms2~10ms5~80msRecall1095-98%90-97%85-92%92-95%内存/1000万条~40GB~30GB~1GB~1GB(RAM)30GB(SSD)建索引速度慢小时级快分钟级快分钟级很慢小时级实时插入支持需重训需重训FreshDiskANN支持删除标记重建可移除可移除FreshDiskANN支持注以上数据基于768维向量、单机环境的近似值实际表现受数据分布、硬件配置和参数调优影响。五个决策问题数据量多大百万级以内HNSW。内存不是问题性能最好。千万级HNSW如果内存够或IVF-PQ如果内存紧张。亿级以上DiskANN。图索引放不进内存只能走磁盘路线。对延迟的要求亚毫秒级1msHNSW。只有图索引能做到这个级别。毫秒级1-10msHNSW或IVF-Flat。十毫秒级可接受IVF-PQ或DiskANN。对召回率的要求95%HNSWef_search调大。IVF-Flat也行nprobe调大。85-95%IVF-PQ可以接受。80% 以下任何方案都行优先选最省资源的。内存预算充足原始数据 ×1.5以上HNSW。有限原始数据 ×0.5左右IVF-PQ。极度有限原始数据 ×0.1以下DiskANN。数据是否频繁更新频繁插入HNSW支持增量插入IVF需要重训聚类中心。频繁删除都不太行。HNSW用标记删除 定期重建IVF可以从区域中移除但聚类中心不变。批量更新定期全量重建无所谓所有方案都支持。一个真实场景的选型推演假设你在做一个RAG系统知识库有500万条768维的文档向量要求P99延迟10ms召回率95%部署在一台64GB内存的机器上。先算内存500万×768维×4字节15GB原始向量数据。HNSWM16图结构约5GB 原始向量15GB 20GB。64GB内存够用。延迟亚毫秒级。召回率调ef_search可以到97%。IVF-Flat原始向量15GB 聚类中心可忽略 15GB。延迟取决于nprobenprobe16时大概5-8ms。召回率约92-95%。IVF-PQm96压缩后约0.5GB。延迟更快2-3ms但召回率因量化损失大概85-90%。DiskANN内存约0.5GBPQ编码SSD存全量。延迟10-30ms。结论适合选HNSW但是也要根据业务可接受的程度看。选型没有银弹。每种索引都是在速度、精度、内存这个三角上做取舍。写在最后索引的本质是用空间换时间。HNSW用更大的内存空间换取更快的查询速度IVF用更少空间换可接受的时间DiskANN用磁盘空间换内存空间。实际生产中一定要进行POC测试后方可上线。学AI大模型的正确顺序千万不要搞错了2026年AI风口已来各行各业的AI渗透肉眼可见超多公司要么转型做AI相关产品要么高薪挖AI技术人才机遇直接摆在眼前有往AI方向发展或者本身有后端编程基础的朋友直接冲AI大模型应用开发转岗超合适就算暂时不打算转岗了解大模型、RAG、Prompt、Agent这些热门概念能上手做简单项目也绝对是求职加分王给大家整理了超全最新的AI大模型应用开发学习清单和资料手把手帮你快速入门学习路线:✅大模型基础认知—大模型核心原理、发展历程、主流模型GPT、文心一言等特点解析✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑✅开发基础能力—Python进阶、API接口调用、大模型开发框架LangChain等实操✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经以上6大模块看似清晰好上手实则每个部分都有扎实的核心内容需要吃透我把大模型的学习全流程已经整理好了抓住AI时代风口轻松解锁职业新可能希望大家都能把握机遇实现薪资/职业跃迁这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】
返回列表