想象你来到一座陌生的“美食之城”,全城有一万家餐厅,你要找出“今晚最合口味”的那一家。挨家挨户试吃显然不现实——这是暴力搜索的困境。这时你有两条聪明路:一条是把城市按风味分成大区,先锁定“川菜区”再逐家细找,这是 IVF(倒排文件索引);另一条是找一位“社交达人”层层介绍,从泛泛之交一路引荐到资深老饕,一步步逼近那家宝藏小店,这是 HNSW(分层小世界图)。两种思路都牺牲一点点“绝对最优”,换来了“足够好且够快”的答案——这正是向量数据库从千万条向量中毫秒级找回相似内容的秘密。读完这篇文章,你会彻底搞懂这两套“导航系统”怎么工作、各有什么脾气,以及实战中如何选型。

岗位关联

掌握 HNSW 与 IVF,你就读懂了 RAG 应用中最关键的检索加速引擎,能直接指导向量数据库的选型与调参,让大模型问答从“等 5 秒”变成“50 毫秒”。

目录
  1. 可视化演示
  2. 初识近似搜索
  3. IVF聚簇索引
  4. HNSW多层导航
  5. 构建流程异同
  6. 查询机制对比
  7. 性能权衡术
  8. 选型实战指南
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示HNSW分层小世界图的多层级导航搜索、IVF聚类倒排缩减搜索范围、以及两种索引在召回率延迟和内存占用上的性能对比。

本节配有交互动效(进入视口后自动加载,约 3KB)。

HNSW分层导航小世界图 多层图结构高层稀疏底层稠密 从顶层入口逐层向下贪心搜索 O(logN) HNSW搜索复杂度为对数级

初识近似搜索

美食家走进城市,首先想到的是翻遍每家餐厅的菜单。他会拿着一本厚厚的“全城餐厅目录”,逐条对比今天想吃的口味。这本目录越厚,翻找的时间就越长。如果全城有一万家店,他要翻一万次——这就是暴力扫描的困境:虽然能找到“绝对最合口味”的那家,但时间成本高到无法接受。

在向量检索的世界里,“餐厅”是文本或图片转化成的向量(比如 Embedding),“合口味”就是向量距离最近。精确最近邻(KNN)要求返回那个距离最近的向量,必须逐个计算查询向量与全部 N 个向量的距离。当 N 以百万计时,逐条计算的耗时就会让搜索变成“灾难”。

于是近似最近邻(ANN)登上舞台:不保证找到“绝对最接近”的那个,而是接受在极短时间内返回“足够接近”的多个候选。用召回率(Recall)来衡量“足够接近”的程度——真正常见的评价指标是 Recall@k。欧氏距离是衡量两个向量“口味差距”的基本标尺:

暴力扫描像走完全城所有街道,近似搜索则用“可能错过几家店”的小代价,换来“几分钟变几毫秒”的大收益。这正是向量索引存在的意义。

d(q⃗,v⃗)=∑i=1d(qi−vi)2\displaystyle d(\vec{q}, \vec{v}) = \sqrt{\sum_{i=1}^{d}(q_i - v_i)^2}
欧氏距离就是“两点之间直线距离”的推广,在向量空间里衡量两个点有多远。
  1. 向量差先计算查询向量与数据向量各维度的差值,就像比较两道菜每项配料的用量差。
    qi−vi\displaystyle q_i - v_i
  2. 逐维平方求和把每个维度的差平方后累加,消除正负抵消,突出大差异项。
    ∑i=1d(qi−vi)2\displaystyle \sum_{i=1}^{d}(q_i - v_i)^2
  3. 开方还原对累加结果开平方,得到具有原始量纲的直线距离。
    ∑i=1d(qi−vi)2\displaystyle \sqrt{\sum_{i=1}^{d}(q_i - v_i)^2}

IVF聚簇索引

聪明的美食家会在出发前先看城市美食地图:川菜扎堆在东区、粤菜聚在南城、日料集中在西街。他先判断自己今天想吃哪一区,再直奔目标区域,在其中逐家筛选。IVF(Inverted File Index,倒排文件索引)用的正是这套“分区治理”逻辑。

IVF 的第一步是用 K-means 聚类把所有向量划分成 nlist 个簇,每个簇有一个质心(中心向量)。这相当于把城市划分成若干“风味区”。查询时,先计算查询向量与每个质心的距离,找到最近的 nprobe 个簇,然后再只在这些簇内部做精细搜索。nprobe 越大,探查的“风味区”越多,搜索越精确但越慢。

簇与向量的归属关系被记录在倒排列表中——本质上是一张“簇 ID → 落在该簇的向量 ID 列表”的映射表。K-means 聚类的目标是让每个向量距离其质心尽量近:

IVF 就像给全城餐厅贴上了区域标签,顾客来时不翻全城目录,只翻对应区域的几页。分区越合理、区域数越适中,“找店”的速度就越快。

min⁡c1,…,ck∑j=1k∑x⃗∈Sj∥x⃗−cj∥2\displaystyle \min_{c_1,\dots,c_k} \sum_{j=1}^{k} \sum_{\vec{x} \in S_j} \|\vec{x} - c_j\|^2
这个目标函数的意思是:找到一组“区域中心”,让每个区里的餐厅到本区中心的平均距离尽可能小。
  1. 簇划分全部向量被划分到 k 个簇 $S_j$ 中,每个向量只属于一个簇。
    Sj⊆{x⃗1,…,x⃗n}S_j \subseteq \{\vec{x}_1,\dots,\vec{x}_n\}
  2. 簇内误差计算簇内每个向量到质心 $c_j$ 的距离平方,衡量该簇的“聚合度”。
    ∥x⃗−cj∥2\|\vec{x} - c_j\|^2
  3. 全局最小化通过迭代调整质心位置,让所有簇的簇内误差总和最小。
    min⁡c1,…,ck∑j=1k∑x⃗∈Sj∥x⃗−cj∥2\displaystyle \min_{c_1,\dots,c_k} \sum_{j=1}^{k} \sum_{\vec{x} \in S_j} \|\vec{x} - c_j\|^2

HNSW多层导航

与“分区细找”不同,HNSW(Hierarchical Navigable Small World,分层小世界图)走的是“人脉带路”路线。你只有一个“泛泛之交”的朋友,但他认识不少圈内人;你让他引荐一位更懂行的朋友,这位朋友又带你认识一位资深美食评论家……每经手一层,推荐质量都更高,离目标餐厅更近。

这套思路源于跳表(Skip List)的启发:跳表用多层链表让查找加速,HNSW 则用多层图做相似搜索。最顶层节点极少、连边稀疏,如同“泛泛之交的大圈子”;越往下节点越多、连边越密,如同“知根知底的小圈子”。搜索时从顶层出发,在每一层沿边做贪心移动——找离查询点最近的邻居——然后坠入下一层继续,直到抵达最底层。

每个节点插入时,其所在最高层由概率公式决定:层数越高,出现的节点越少,形成金字塔结构。边连接的是“在某层相互接近”的节点,使整个图具备小世界特性——任意两点只需很少的跳数即可连通,如同“六度分隔”理论:

HNSW 像一张“熟人推荐网络”,每一步都借由“跳得远”的节点快速逼近目标,又靠“走得准”的底层节点锁定答案。这就是它能在高召回率下保持低延迟的原因。

P(l)=exp⁡(−lmL)\displaystyle P(l) = \exp\left(-\frac{l}{m_L}\right)
这条公式描述节点出现在第 l 层的概率:层数越高,概率指数下降,所以顶层总是稀稀疏疏,底层总是熙熙攘攘。
  1. 层数变量$l$ 表示节点所在的层号,0 是最底层。
    l\displaystyle l
  2. 指数衰减概率随层数 $l$ 指数下降,高层的节点天然稀少。
    exp⁡(−lmL)\displaystyle \exp\left(-\frac{l}{m_L}\right)
  3. 尺度参数$m_L$ 控制衰减速度,$m_L$ 越大,节点越容易进入更高的层,顶层也越“拥挤”。
    lmL\displaystyle \frac{l}{m_L}

构建流程异同

两种找餐厅策略都需要“事前准备”。分区策略要在开业前做好城市功能区规划、给每家餐厅登记造册;人脉策略则要靠每一位朋友逐步积累关系。两者的准备成本和时间节奏有显著差异。

IVF 的构建分两步:先用全量数据训练 K-means,得到 nlist 个质心;再遍历所有向量,为每个向量找最近的质心并写入对应的倒排列表。训练过程需要多次迭代,数据量越大、簇数越多,训练耗时越长。HNSW 的构建则是逐个插入向量:每插入一个,就执行一次“从上到下找位置、再逐层建立连接”的过程,全程无需全局重训。

增量更新方面,IVF 天然支持“新向量直接分配到已有簇”的增量添加;HNSW 也可以增量插入,但删除操作实现复杂、代价高。内存占用上,IVF 需要存质心与倒排链表,HNSW 需要存多层图的邻接表,通常 HNSW 的额外开销更大。IVF 的构建时间复杂度可写为:

如果说 IVF 是“开张前统一划分商圈”,那 HNSW 就是“边开店边扩人脉”。前者胜在批量高效,后者胜在灵活弹性,两者构建期的性格完全不同。

TIVF=O(N×k×t)\displaystyle T_{IVF} = O(N \times k \times t)
意思是:构建耗时 ≈ 样本数 × 簇数 × 迭代轮数,三者共同决定训练要花多久。
  1. 样本规模N 表示全量向量数,每个向量都要参与距离计算。
    N\displaystyle N
  2. 质心距离k 表示簇数,每轮迭代要算每个样本到所有质心的距离。
    k\displaystyle k
  3. 迭代轮数t 表示 K-means 收敛所需的迭代次数。
    t\displaystyle t

查询机制对比

客人上门时,分区策略的店员会先问“您想去哪个区”,然后带你到那个区里逛;人脉策略的引荐人则是一层一层地介绍,每层判断一次“该带你去见谁”。两种查询过程各有各的节奏。

IVF 查询时由 nprobe 控制“探查几个候选簇”:nprobe 越小,只看最像的 1 个簇,速度快但可能漏掉真正的目标;nprobe 越大,探的簇越多,召回率越高但耗时上升。HNSW 查询时由 efSearch 控制“每层维护多大的候选队列”:队列越大,搜索时记得住的候选项越多,越不容易走弯路,但代价是更多比较。

HNSW 的核心搜索策略是贪心搜索:从顶层某个入口节点出发,每一跳都选择邻居中离查询点最近的那个,重复该过程直到邻居不再更近,然后进入下一层继续。每层的贪心移动可表示为:

一个是“精准但粗线条的分区导览”,一个是“一步比一步更懂行的熟人带路”。nprobe 与 efSearch 就是这两种策略的“耐心旋钮”,旋得越大,结果越可靠,代价也越高。

vnext=arg⁡min⁡u∈N(v)∥q−u∥\displaystyle v_{next} = \arg\min_{u \in \mathcal{N}(v)} \|q - u\|
这一公式描述:在当前节点的所有邻居里,挑一个离查询点最近的,作为下一跳。
  1. 邻居集合$\mathcal{N}(v)$ 是当前节点 v 在当前层所有邻居的集合。
    N(v)\displaystyle \mathcal{N}(v)
  2. 距离比较\|q - u\| 是候选邻居 u 与查询向量 q 的欧氏距离。
    ∥q−u∥\displaystyle \|q - u\|
  3. 贪心选择取距离最小的邻居作为下一跳,不断逼近目标区域。
    vnext=arg⁡min⁡u∈N(v)∥q−u∥\displaystyle v_{next} = \arg\min_{u \in \mathcal{N}(v)} \|q - u\|

性能权衡术

想快、想准、想省内存——这就像餐厅想同时做到“客流大、菜品精、店面小”一样,很难兼得。向量索引的选择本质上是在三张牌桌上权衡:召回率、延迟、内存。

召回率是衡量“找得准不准”的核心指标——Recall@k 表示真实前 k 个最近邻中有多少个被索引成功召回。延迟(QPS)衡量“找得快不快”,内存衡量“装得下多少”。IVF 在 nprobe 调小时非常快、内存省,但召回率有限;HNSW 通常召回率更高、延迟更低,但内存开销和构建时间更大。

公式上,Recall@k 的定义是:

好的“火候”需要反复试:nprobe、efSearch、每层最大度数 M 都是厨师手里的旋钮。调参的本质,就是在召回率、延迟和内存之间找到那道最合口味的平衡线。

Recall@k=∣GTk(q)∩ANNk(q)∣k\displaystyle \text{Recall}@k = \frac{|GT_k(q) \cap ANN_k(q)|}{k}
召回率就是“正确答案里有多少被找回来了”:全找回来是 1.0,找回一半是 0.5。
  1. 真值集合$GT_k(q)$ 是用暴力扫描得到的、和查询向量 q 最相近的前 k 个向量。
    GTk(q)\displaystyle GT_k(q)
  2. 预测集合$ANN_k(q)$ 是索引结构返回的前 k 个候选向量。
    ANNk(q)\displaystyle ANN_k(q)
  3. 交集占比两个集合重合的数量除以 k,得到 0 到 1 之间的召回率。
    ∣GTk(q)∩ANNk(q)∣k\displaystyle \frac{|GT_k(q) \cap ANN_k(q)|}{k}

选型实战指南

是选“分区找餐厅”还是“熟人带路”?这取决于城市的大小、顾客的耐心和餐厅的密度。没有绝对优劣,只有是否匹配场景。

一般来说,当数据量在百万级以下、内存有限、且数据持续高频新增时,优先考虑 IVF——它构建快、内存省、增量友好;当数据量达到千万级、需要极高召回率和稳定低延迟时,HNSW 是更优选择,但需要接受更大的内存和更长的构建时间。Faiss 中还提供了混合思路:用 IVF 先做粗筛,把搜索范围缩小到少数几个簇,再在簇内用 HNSW 精细检索——即 IVF-HNSW 混合索引,兼顾两者的优点。

实战选型可以构建一个带权评分公式来量化判断:

选型的终点不是“哪一个最好”,而是“哪一个最合适”。在 RAG 系统中,数据规模、更新频率、延迟预算共同决定你的答案——有时分区,有时带路,有时两者都上。

Score(I)=Recall(I)αw1×Latency(I)+w2×Memory(I)\displaystyle \text{Score}(I) = \frac{\text{Recall}(I)^\alpha}{w_1 \times \text{Latency}(I) + w_2 \times \text{Memory}(I)}
评分公式的含义:索引的“得分”等于召回率的幂次除以延迟和内存的加权和——得分越高,越适合当前场景。
  1. 收益项$\text{Recall}(I)^\alpha$ 将召回率作为主要收益,$\alpha$ 控制对召回率的重视程度。
    Recall(I)α\displaystyle \text{Recall}(I)^\alpha
  2. 代价项$w_1 \times \text{Latency}(I) + w_2 \times \text{Memory}(I)$ 是延迟与内存的加权总和。
    w1×Latency(I)+w2×Memory(I)\displaystyle w_1 \times \text{Latency}(I) + w_2 \times \text{Memory}(I)
  3. 综合评分收益越高、代价越低,得分越高,对应越适合该场景。
    Score(I)=Recall(I)αw1×Latency(I)+w2×Memory(I)\displaystyle \text{Score}(I) = \frac{\text{Recall}(I)^\alpha}{w_1 \times \text{Latency}(I) + w_2 \times \text{Memory}(I)}

AI 应用场景

RAG知识库问答的检索加速

阶段:在线检索阶段

解决的问题:文档被切成段落并向量化后,用户提问需要从上百万个片段中快速找回最相关的几个。传统的 BM25 关键词匹配无法处理语义近似,暴力扫描向量又太慢。HNSW 索引让语义检索在毫秒级完成,直接决定大模型回答的质量和体验。

具体案例:某企业内部智能客服系统接入 120 万条政策文档,使用 HNSW 索引(efSearch=128),将平均检索延迟从 1.2 秒压到 45 毫秒,top-5 召回率从 71% 提升到 94%。系统把检索到的段落拼进 Prompt,交给大模型生成回答。

商品推荐中的相似召回

阶段:召回阶段(粗排前)

解决的问题:用户浏览一件商品后,需要从千万级商品池中快速找出“相似商品”。用向量表达商品的图片与文本特征后,用 IVF 先按品类粗分,再在簇内精细搜索,在保证召回率的同时把延迟压在 10ms 以内。

具体案例:某电商平台使用 IVF+HNSW 混合索引,用 IVF 将 1500 万商品粗筛到 500 个候选,再在候选上用 HNSW 精细排序,实现单次召回 8ms、QPS 超 1 万的实时推荐服务。

图片去重与相似图片搜索

阶段:离线索引构建 + 在线查询

解决的问题:内容审核平台需要快速判定“新上传图片是否与黑库图片相似”。用卷积神经网络将图片提取为 512 维向量后,用 HNSW 构建索引,代替逐张比对。

具体案例:某内容审核平台每日处理 1000 万张图片,对每张图片提取 512 维 Embedding 构建 HNSW 索引,单图查询耗时 10ms,重复图片拦截准确率高达 99.2%。

Python 演示

python55 行
# -*- coding: utf-8 -*-"""使用 Faiss 对比 IVF 与 HNSW 两种向量索引的构建与查询"""import timeimport numpy as npimport faiss  def recall_at_k(pred_ids, truth_ids, k):    """计算召回率:预测前k个与真值前k个的交集比例"""    return len(set(pred_ids[0].tolist()) & set(truth_ids[0].tolist())) / k  def main():    dim = 128    n_samples = 10000    np.random.seed(0)    data = np.random.random((n_samples, dim)).astype('float32')     flat_index = faiss.IndexFlatL2(dim)   # 暴力索引,作为真值基线    flat_index.add(data)     nlist = 100                           # 聚类簇数    quantizer = faiss.IndexFlatL2(dim)    ivf_index = faiss.IndexIVFFlat(quantizer, dim, nlist)    ivf_index.train(data)                 # 训练K-means得到质心    ivf_index.add(data)                   # 向量写入倒排列表     m = 32                                # HNSW每节点最大连接数    hnsw_index = faiss.IndexHNSWFlat(dim, m)    hnsw_index.add(data)                  # 逐点插入建图     query = np.random.random((1, dim)).astype('float32')    k = 10     _, truth = flat_index.search(query, k)     # 暴力搜索真值     ivf_index.nprobe = 10                 # 探查最近10个簇    start = time.time()    _, ivf_ids = ivf_index.search(query, k)    ivf_time = time.time() - start     hnsw_index.hnsw.efSearch = 64         # 候选队列大小    start = time.time()    _, hnsw_ids = hnsw_index.search(query, k)    hnsw_time = time.time() - start     print("===== IVF vs HNSW 对比结果 =====")    print(f"IVF  耗时 {ivf_time * 1000:6.2f} ms,"          f"Recall@{k} = {recall_at_k(ivf_ids, truth, k):.2f}")    print(f"HNSW 耗时 {hnsw_time * 1000:6.2f} ms,"          f"Recall@{k} = {recall_at_k(hnsw_ids, truth, k):.2f}")  if __name__ == '__main__':    main()
目的:在 1 万条 128 维向量上分别构建 IVF 与 HNSW 索引,对比两者在查询耗时和召回率上的差异。
  1. quantizer = faiss.IndexFlatL2(dim)创建 L2 距离量化器,IVF 用它判断查询向量离哪个簇中心最近。
  2. ivf_index.train(data)训练阶段,运行 K-means 得到 nlist 个质心向量。
  3. ivf_index.add(data)将全量向量分配到最近的簇,写入倒排列表。
  4. ivf_index.nprobe = 10查询时探查最近的 10 个簇,nprobe 越大越精确但越慢。
  5. hnsw_index.hnsw.efSearch = 64控制 HNSW 搜索时维护的候选队列大小。
  6. recall_at_k(ivf_ids, truth, k)自定义召回率函数,衡量近似索引与暴力真值的结果重合度。

常见误区

误区既然 IVF 是靠“分区”来缩小范围,那把 nlist 调得非常大,每个区都很小,不是应该更精确吗?我直接把 nlist 设为 10000,结果反而变慢了,召回率也没提升。

正解nlist 过大会导致每个簇里的样本太少,质心估计不准,反而让查询点到正确簇的距离变远;同时训练阶段的计算量(N×k×t)随 k 线性上升,构建时间急剧膨胀。nlist 的最优值通常与数据规模匹配,例如 100 万条向量时取 nlist=1000~4000 是经验区间。

为何常见:直觉上“划分得越细,越容易找到目标”,但忽略了质心也是从样本中估出来的——簇太小,质心本身就不稳。

误区HNSW 既然能通过图一层层导航,那它最后找到的应该就是全局最近邻吧?毕竟每一步都在往更近的方向走。

正解HNSW 是近似算法,贪心搜索可能陷入局部最优。当图中有“捷径缺失”时,最邻近节点可能藏在一个当前节点邻居覆盖不到的角落。所以工程上需要用 Recall@k 来量化它的“近似程度”,而不是假设它等于暴力搜索。

为何常见:人们习惯于把“看起来能全局搜索”的图结构理想化,忽略了贪心策略本质上只看局部信息。

误区教程里把 IVF 和 HNSW 分开讲,那我部署时就应该从中挑一个,要么用 IVF 要么用 HNSW。

正解两者可以组合使用。Faiss 提供了 IVF-HNSW 混合索引:先用 IVF 聚类粗筛,把候选压缩到少量簇内,再在这些簇上用 HNSW 精细检索。这种组合在千万级数据上兼顾了 IVF 的低内存与 HNSW 的高召回。

为何常见:教材为了降低理解难度,往往把两类算法放在对立面对比,容易让人误以为它们互斥。

误区模型训练完、索引建好了,之后就不用管了。用户怎么查都能保证又快又准。

正解数据分布是动态变化的。当新增向量大量涌入时,IVF 的质心可能过时,HNSW 的图结构可能失衡;删除操作尤其棘手。生产环境需要定期评估 Recall@k 和延迟,必要时重建索引或做参数热调。

为何常见:初学阶段用一次性静态数据做实验,很容易忽略真实场景中数据持续增长带来的漂移问题。

误区只要把 nprobe 和 efSearch 调到最大,召回率接近 100%,系统慢一点也能接受。毕竟“准确”比“快”重要。

正解在 RAG 问答、实时推荐等场景中,延迟直接决定用户体验。召回率从 95% 提到 99% 可能需要 5 倍延迟,而 95% 的召回对下游大模型往往已经足够。正确的做法是设定延迟预算,在预算内最大化召回率。

为何常见:学术评测常以召回率为核心指标,容易让人忽略工业场景中延迟和吞吐量同样是硬约束。

面试题

Q1. 向量检索中的 ANN 缩写代表什么?

单选题 · easy

  • A.近似最近邻搜索← 正确答案
  • B.精确最近邻搜索
  • C.人工神经网络
  • D.自动最近邻索引

答案:A。ANN 在向量检索语境下是 Approximate Nearest Neighbor(近似最近邻搜索);虽然 ANN 在深度学习里也常指人工神经网络(Artificial Neural Network),但本题问的是向量检索场景,故选 A。B 是精确最近邻(KNN),D 是干扰项。

Q2. IVF 索引中 nlist 参数的用途是什么?

单选题 · easy

  • A.聚类划分的簇总数← 正确答案
  • B.查询探测的簇个数
  • C.向量数据的维度
  • D.返回结果的个数

答案:A。nlist 是 IVF 训练时 K-means 聚类的簇数量,决定把向量空间切分成多少“风味区”。B 是 nprobe 的职责,C 是向量维度 d,D 是搜索的 top-k。容易把 nlist 和 nprobe 混淆。

Q3. HNSW 中的 efSearch 参数控制什么?

单选题 · easy

  • A.查询候选队列大小← 正确答案
  • B.每层最大连边数量
  • C.图中总节点个数
  • D.插入时的批大小

答案:A。efSearch 控制搜索时维护的动态候选队列大小,队列越大探索越充分,召回越高但耗时越大。每层最大连边数由 M 控制,节点数由数据量决定,插入批大小与 efSearch 无关。

Q4. 暴力最近邻搜索的时间复杂度是?

单选题 · mid

  • A.与数据量大小成正比
  • B.与数据量和维度成正比← 正确答案
  • C.与数据量的对数成正比
  • D.与数据量的平方成正比

答案:B。暴力搜索要计算查询向量与全部 N 个向量的距离,而每个距离计算要遍历 d 个维度,所以复杂度是 O(N×d),即与数据量和维度都成正比。A 忽略了维度,C 是对数级复杂度,D 是 O(N²) 的错误估计。

Q5. IVF 查询时 nprobe 越大,通常会导致?

单选题 · mid

  • A.召回率越高延迟越高← 正确答案
  • B.召回率越低延迟越高
  • C.召回率越高延迟越低
  • D.召回率不变延迟降低

答案:A。nprobe 表示查询时探测的候选簇数量。探测的簇越多,覆盖的真实最近邻越可能被找到,召回率上升;但要比较的距离也越多,延迟随之上升。所以 A 正确,其余组合不符合实际。

Q6. 关于 HNSW 相比 IVF 的特点,以下正确的有?

多选题 · hard

  • A.通常查询召回率更高← 正确答案
  • B.构建速度通常更快
  • C.内存占用通常更大← 正确答案
  • D.更适合分布式部署

答案:AC。HNSW 的多层图结构能在较少比较次数内逼近全局最近邻,召回率通常更高,A 正确;它需要存储每层的邻居边,内存开销大于 IVF 的倒排列表,C 正确。构建速度上 HNSW 逐点插入通常慢于 IVF 批量训练,B 错误;图结构的切分难题使 HNSW 分布式部署更困难,D 错误。

Q7. Recall@k 的计算方式是?

单选题 · mid

  • A.预测真值交集数除以 k← 正确答案
  • B.查询结果平均距离除以 k
  • C.索引构建时间除以 k
  • D.数据总量除以返回结果数

答案:A。Recall@k = |GT_k ∩ ANN_k| / k,即真值集合与近似结果集合的交集数量除以 k,衡量“正确答案有多少被找回来了”。B、C、D 分别涉及距离、构建时间和数据量,都与召回率定义无关。

Q8. 以下哪些场景更适合选择 IVF?

多选题 · hard

  • A.千万级向量但内存非常有限← 正确答案
  • B.数据持续高频新增插入← 正确答案
  • C.要求极高召回率的在线推荐
  • D.数据规模百万级且分布均匀← 正确答案

答案:ABD。IVF 内存占用低,适合内存受限场景,A 正确;新向量可直接分配到已有簇,增量友好,B 正确;百万级均匀分布数据是 IVF 的舒适区,D 正确。C 中极高召回率要求更适合 HNSW 或加大 nprobe 的 IVF,但单纯 IVF 通常难满足。

Q9. HNSW 搜索过程的特点包括?

多选题 · mid

  • A.从最顶层稀疏图开始搜索← 正确答案
  • B.底层使用候选队列拓展← 正确答案
  • C.每层都做贪心最近邻跳转← 正确答案
  • D.搜索前需要聚类训练

答案:ABC。HNSW 从最顶层出发,逐层做贪心最近邻跳转,到底层后通过 efSearch 大小的候选队列精细拓展,A、B、C 都正确。D 是 IVF 的训练流程,HNSW 建图不需要聚类。

Q10. 用 Faiss 组合 IVF 和 HNSW 的目的是?

单选题 · hard

  • A.先用聚类粗筛再用图精搜← 正确答案
  • B.用图替代倒排减少内存
  • C.用聚类替代图减少延迟
  • D.两者互相替代并无优势

答案:A。IVF-HNSW 混合索引的含义是:先用 IVF 聚类把千万级数据粗筛到少量候选簇,缩小搜索范围;再在候选簇内用 HNSW 精细检索,兼顾低内存与高召回。B、C 把两者的角色反了,D 否定了组合价值。