土法炼钢兴趣小组的算法知识备份

【向量检索引擎】ANN 算法工程接口:从 HNSW/IVF 到 Knowhere 契约

文章导航

分类入口
databasestorage
标签入口
#ann#hnsw#ivf#diskann#knowhere#milvus#index-params#vector-engine

目录

db-frontier/08 讲清了 HNSW、DiskANN、IVF-PQ 的图/倒排假设与召回–QPS–内存三角。第 8 篇 讲清了 Knowhere 的 VecIndex 类层次与工厂。中间还缺一张 工程师调参时看见的接口表:集合上声明哪种索引、哪些参数属于构建期、哪些属于查询期、Flat 在引擎里扮演什么角色。

本文不重证小世界图性质,只建立 算法名 → 引擎契约 的翻译层。

本文是「向量检索引擎」系列第 2 篇(共 19 篇)。→ 系列目录

版本锚定:Milvus 2.6.x Knowhere / Architecture;算法细节外链 frontier/08。


一、最小故事:你改的到底是哪一类旋钮

假设 Collection 已建好 HNSW。业务说「召回不够」,同学 A 把 ef 从 64 调到 128;同学 B 把 M 从 16 调到 32。两者都可能改善召回,但 运维代价完全不同

排障时若分不清这两类旋钮,就会把「改配置立刻生效」的期望套到必须重建的参数上——延迟尖刺与召回掉点会一起出现。本文先把契约钉住,再把类型表与 Segment / 过滤接点讲清。


二、引擎需要的不是论文,是四个动词

生产路径里,ANN 对引擎暴露的能力可以收成:

动词 含义 典型发生位置
Train 需要训练的结构(如 IVF 质心)在数据上拟合 Data Node 建索 / Knowhere
Build / Add 把段内向量写入索引结构 同上
Serialize / Load 索引落对象存储,Query Node 加载 第 6、7、10 篇
Search / Query 带可选 bitset 掩码的近似 Top-\(k\) Segcore → Knowhere

Knowhere 文档强调:与经典「训练集 / 测试集分离」不同,段内数据既用于 train 也用于 search。因此索引生命周期 贴着 Sealed segment,而不是贴着全局离线竞赛设定(第 3、10 篇)。

flowchart LR
  sealed["Sealed segment"]
  train["Train"]
  build["Build / Add"]
  ser["Serialize to object store"]
  load["Load on Query Node"]
  search["Search / Query + bitset"]
  sealed --> train --> build --> ser --> load --> search

2.1 召回–QPS–内存三角(接口层示意)

frontier/08 已给出算法层三角。引擎侧只记住:任意索引类型都在三点之间取舍,调参是在三角形边上滑动,不是同时把三点推到最优。

flowchart TB
  recall["Recall"]
  qps["QPS / latency"]
  mem["Memory / disk"]
  recall --- qps
  qps --- mem
  mem --- recall

本图 不含数字:具体曲线依赖维度、数据集与硬件。线上调参应用自己的 golden set 测 Recall@\(k\) 与延迟中位数(第 17 篇),不要抄营销页上的「提升 30%」。


三、类型速查:算法假设 → 引擎选型直觉

下表只给 接口层直觉;复杂度与参数精调见 frontier/08 与 llm-infra/18。

引擎侧常见类型 算法家族 内存/磁盘假设 何时优先考虑
FLAT / IDMAP 暴力 全向量常驻计算 召回金标准、小段、调参对照
IVF_FLAT / IVF_PQ / IVF_SQ* 倒排 + 可选量化 列表扫描;PQ 换内存 可接受训练、偏吞吐/压缩
HNSW 分层小世界图 高内存图 低延迟内存检索主流默认
DiskANN 等 磁盘友好图 索引主要在盘/对象侧 单机内存装不下全体图
二进制族 Hamming 等 压缩二值向量 指纹/化学等二值特征

Architecture Overview 写明 Milvus 构建在 Faiss、HNSW、DiskANN、SCANN 等库之上;具体 release 启用哪些 index_type 字符串以当时 Index 文档为准。

3.1 构建期 vs 查询期参数

阶段 例子(概念名) 工程含义
构建期 HNSW 的 MefConstruction;IVF 的 nlist 改了通常要 重建索引
查询期 HNSW 的 ef;IVF 的 nprobe 可按请求调节延迟/召回,不必重建

把查询期参数当成「免费旋钮」、把构建期参数当成「变更窗口」——排障时先分清改的是哪一类。

3.2 Flat 的系统角色

Knowhere 把 IDMAP 也做成 VecIndex:无 train/build,查询直接打原始向量。系统用途:

  1. 离线算 Recall@\(k\) 的 ground truth;
  2. 小数据或索引未就绪时的正确性路径;
  3. 对比「加索引后掉了多少召回」的基线。

不要在十亿级集合上把 Flat 当默认在线索引。

3.3 教学示意:同一段上的两种搜索

设某 Sealed 段有 \(N=10^5\) 向量。Flat 对每次查询做约 \(N\) 次距离;HNSW 在合适 ef 下只访问图的一个子图。引擎不会自动告诉你「这段该用哪种」——选型是 schema / index 配置决策,代价在 Data Node 建索与 Query Node 内存上显现(第 8、10 篇)。

3.4 参数落点:SDK 字符串如何进 Knowhere

工程师在 SDK 里通常看到两层配置(名称以官方 Index 文档为准,随 release 微调):

配置面 典型字段 落到契约的哪一动词
index_type HNSW / IVF_FLAT / DISKANN / … 选择哪一个 VecIndex 实现
metric_type L2 / IP / COSINE 距离定义;与向量是否归一化强相关
构建 params MefConstructionnlist、… Train / Build
查询 params efnprobe、… Search

度量与归一化IP / COSINE 混用、或未归一化却声明余弦,会在「参数看起来合理、召回却怪」的案例里反复出现——第 17 篇排障清单会再钉一次。本篇只要求:度量是契约的一部分,不是事后装饰。

3.5 Growing 上还没有「最终索引」时搜什么

Data Processing 把实时可搜钉在 Growing 路径:WAL 提交后即可参与查询,但 最终 ANN 结构(例如完整 HNSW)往往在 Sealed 上由 Data Node 构建。引擎可能在 Growing 侧使用更轻的临时结构或暴力路径(具体以当时 release 的 interim index 配置为准,见 queryNode.segcore.*,第 7 篇)。

对学生的含义:「Collection 声明了 HNSW」≠「刚写入的那一行已经在一张建好的 HNSW 里」。声明描述的是 Sealed 目标形态;实时路径另有可搜保证。


四、与 Segment / 过滤的接口接点

  1. 每 Sealed 一段一索引(Data Processing)→ 全局一次 search = 多索引候选归并(第 9 篇)。
  2. bitset 软删与属性过滤(Bitset / Knowhere)→ Search 必须接受「哪些行仍参与」的掩码(第 11、13 篇)。
  3. Growing 路径可能尚无最终 ANN 结构 → 实时可搜 ≠ 最终索引形态(第 5、10 篇)。

选择度很低的标量过滤会让「局部 Top-\(k\) 再合并」失效——这是算法三角之外的第四个变量,展开见第 11 篇与 db-frontier/09

flowchart TB
  expr["Scalar expression"]
  bitset["Filter + delete bitset"]
  kh["Knowhere Search"]
  reduce["Segment / shard / Proxy reduce"]
  expr --> bitset --> kh --> reduce

五、常见误解

  1. 「调大 ef / nprobe 就等于换了更好的索引」。查询期参数只在 已有图/倒排结构 上多探一些邻居;结构本身由构建期参数决定。
  2. 「Collection 上声明一次 HNSW,全集群共享一张图」。实现是 每 Sealed segment 一份索引;Growing 路径另算。
  3. 「Flat 太慢所以线上永远不该出现」。评估召回时 Flat(或等价精确路径)仍是金标准;问题在于 把 Flat 当默认生产索引

六、插件契约(回指第 8 篇)

向 Knowhere 增加索引类型的官方步骤:IndexEnumConfAdapter 校验 → 实现 VecIndexVecIndexFactory → unittest。量化系参考 IVF_FLAT,图系参考 HNSW,树系参考 Annoy

本篇对应用的含义:你在 SDK 里填的 index_type / params,最终要落到某一 VecIndex 实现的 Train/Query;没有实现的字符串不是「配置写错了就会自动降级」的承诺


七、学术谱系、工程间隙与开放问题

代表 本文角色
算法 Malkov HNSW;DiskANN;IVF-PQ 外链 frontier/08
Faiss / Hnswlib Knowhere 之下
契约 VecIndex 四动词 + 段生命周期 本篇
系统 Milvus Workers 第 7–10 篇

谱系分叉点:ANN 论文优化「给定静态 \(X\) 建一个索引再查」;向量 DBMS(SIGMOD 2021)要求动态更新。Knowhere 的段内 Train/Search 同数据,是后者在索引插件层的落点——不要用静态 benchmark 的最优参数当生产默认值而不做过滤与多段评测

工程间隙

开放问题

  1. 多向量字段时,单段多索引的参数面如何避免组合爆炸?
  2. 磁盘索引与对象存储冷热分层如何共用同一套 Load 语义(第 6、18 篇)?
  3. 过滤选择度进入契约后,查询期参数是否应随谓词自适应(算法侧见 frontier/09;引擎侧见第 11 篇)?

八、小结

三句话小结

  1. ANN 进引擎后变成 Train / Build / Load / Search 契约,索引贴着 Sealed segment。
  2. 构建期与查询期参数运维代价不同;Flat 是金标准,不是默认线上索引。
  3. 过滤 bitset 与多段归并是三角之外的第四个变量——见第 11、9 篇。

下一篇进入数据模型:Segment 状态机;Knowhere 实现见 第 8 篇


参考资料

  1. Milvus Documentation v2.6.x, KnowhereArchitecture OverviewData Processing
  2. db-frontier/08db-frontier/09
  3. 第 8 篇 Knowhere系列 index

返回 系列目录 | 上一篇:向量引擎全景 | 下一篇:Segment 状态机

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-07-12 · database / storage

【向量检索引擎】Knowhere:向量索引执行引擎与插件契约

按官方 Knowhere 文档说明其在 Milvus 中的位置、相对 Faiss 的扩展(bitset、SIMD 选择、二进制度量)、VecIndex 类层次与 IDMAP/IVF/HNSW 等类型,用插件注册、CPU/GPU 分发与 bitset 进查询三张图钉住工程契约,并与 db-frontier/08 的算法细节分工。


By .