HNSW 是怎么做近似最近邻的?相比暴力检索牺牲了什么?

Q2-07向量索引常见HNSWANN近似最近邻索引参数召回率

谁在问:有算法背景的面试官、基础架构团队二面;简历写了向量库调优必被追

口语化问法

  • 向量检索底层是怎么做到毫秒级的?总不能挨个算距离吧。
  • HNSW 讲一下原理。
  • 你们索引参数怎么配的?召回率不够的时候调什么?

考察意图

这题筛的是「知道向量库怎么用」和「知道它为什么快」的差别。三个递进的观察点:① 你有没有意识到 Approximate(近似) 这个词本身就是一个权衡声明;② 能不能讲清多层图的机制而不是背名词;③ 知不知道哪个参数是运行时可调的——这个细节骗不了人,只有真调过的人才会脱口而出 ef_search

参考答案

图 2 · 60 分与 90 分差在哪:代价、演进、怎么验证

60

60 分答案(及格线)

HNSW 全称分层可导航小世界图。核心思路是建一个多层图结构:上层节点稀疏、边跨度大,用来做长距离跳跃;下层节点稠密,用来精细定位。检索时从顶层入口点出发,每层贪心地走向离目标向量更近的邻居,走不动了就下沉一层,直到底层输出 Top-K。复杂度从暴力检索的 O(N) 降到大约 O(log N)。

牺牲的是精确性——它是近似最近邻,不保证 100% 找到真正的最近邻,可能会漏。换来的是几个数量级的速度提升。另外它的图结构常驻内存,内存开销较大。

90

90 分答案(有生产经验的回答)

在原理之上补三块:

一个好类比:像查地图找店。顶层只有城市(北京→上海一步到位),中层是区(跳到黄浦区),底层是具体街道(小范围精找)。每层内部是「小世界」网络——任意两点跳几步就能到,所以贪心走很快收敛。

三个参数及其可调性

参数 作用 调大的后果 何时可改
M 每节点邻居数 召回↑、内存↑、构建慢 建索引时定,改需重建
ef_construction 建索引时候选队列长度 索引质量↑、建得更慢 建索引时定,改需重建
ef_search 查询时候选队列长度 召回↑、查询变慢 运行时可调,无需重建

所以「召回率不够怎么办」的第一反应应该是 先调 ef_search 看看——零成本、立刻见效。这比重建索引或换模型便宜得多。

三个必须知道的代价:① 内存常驻,千万级向量时内存可能先于 CPU 成为瓶颈;② 召回非 100%,ef_search 太小会漏;③ 删除是软删除(图结构不好真删,一般打标记跳过),删除比例高了会让图劣化、召回下降,需要定期 compact 或重建。

再补一句横向定位:HNSW 不是唯一选择——IVF(先聚类,只搜几个簇,内存友好但召回略低)、DiskANN(索引放 SSD,适合内存装不下的超大规模)、量化(标量/乘积/二值量化,用精度换内存,可压到几分之一)。选型取决于内存预算和规模。

追问链

图 1 · 五层追问树:面试官会往哪儿挖
从「为什么快」挖到「哪个旋钮能在线拧」,再到 1 亿条还撑不撑

  1. 为什么分层能加速?只用一层稠密图不行吗?

    期望单层贪心易陷局部最优,从随机入口走到目标要很多步;分层让上层「粗定位、大跨步」把起点直接送到目标附近,下层只做局部精搜 —— 本质是用层次结构把搜索路径变短
    信号说得出「避免局部最优 + 缩短路径」→ 真理解;只说「分层就是快」→ 背诵
  2. 召回率不达标,你会先调哪个参数?为什么?

    期望先调 ef_search —— 唯一的运行时参数,不用重建索引,代价只是查询变慢;调到延迟预算上限仍不够,才增大 M / ef_construction 重建索引 → 再回头查是不是 embedding、分块的问题
    信号本题最强的实操探针:答不出 ef_search 可在线调 → 基本没调过参
  3. HNSW 的内存大概怎么估?100 万条 1536 维向量要多少?

    期望1536 × 4 字节 ≈ 6KB/条 → 100 万条约 6GB → 再加图结构开销(与 M 相关,是向量本身的一个可观比例),所以实际预留要明显高于 6GB。优化手段:降维(见 Q2-06)、量化
    信号当场能粗算 → 做过容量规划;完全没概念 → 多半没上过规模
  4. 文档删除了,索引里怎么处理?删多了会怎样?

    期望多数实现是软删除(打标记、检索时跳过),空间不立即释放;删除比例高 → 图连通性劣化、召回下降、查询变慢 → 定期 compact 或重建。工程上用版本号/时间戳元数据过滤旧版本再异步清理,避免更新期出现检索空窗
    信号以为向量库删除和数据库 DELETE 一样即时干净 → 没运维过
  5. 数据从 100 万涨到 1 亿,你这套还能用吗?

    期望单机 HNSW 内存先扛不住。按序:① 量化压缩(乘积量化可压到几分之一)→ ② 换 DiskANN 类磁盘索引 → ③ 上 Milvus 这类分布式做分片 → ④ 业务侧按租户/时间分区,缩小单次检索范围。每条都要同时说出代价:量化掉精度、分布式增运维、分区限制跨域检索
    信号只说「换 Milvus」、不谈量化和分区 → 方案单一
一句「ef_search 可以在线调」就把「读过论文」和「调过库」切开了 —— 第 2 层是这题的闸门;第 3、4 层再验容量规划与软删除运维。

评分要点

  1. 说清多层图结构与「上层跳跃、下层精搜」的机制
  2. 明确指出「近似」是核心权衡,召回非 100%
  3. 能给出复杂度量级(O(log N) vs O(N))
  4. 说得出三个参数及各自影响
  5. 知道 ef_search 是运行时可调的唯一旋钮
  6. 知道内存开销大这一代价
  7. 加分:知道软删除及其对召回的长期影响
  8. 加分:知道 IVF / DiskANN / 量化等替代方案及适用

常见错误

只说「HNSW 是一种图索引,速度快」,讲不出为什么快。
完全不提「近似」这个前提,把它当成精确检索。
三个参数说不全,或把 ef_searchef_construction 搞混。
认为向量库删除是即时物理删除。
讲了一堆原理但答不出任何一个能上手调的参数——典型的读过论文没调过库。

关联学习