向量相似性搜索详解:Flat Index、IVF 与 HNSW

简介: 向量搜索解决非结构化数据(如文本、音频)的语义检索难题。关系型数据库擅长精确匹配结构化数据,而向量数据库通过Embedding将语义转化为向量,并利用余弦相似度、Flat Index、IVF、HNSW等算法实现高效近邻搜索,兼顾精度与速度。

要理解向量搜索先要弄清楚为什么需要向量数据库,关系型数据库处理结构化数据得心应手。所谓结构化数据就是那些具有固定列的表格数据,比如说:姓名、年龄、薪资、日期。这类数据精确匹配查询很简单:"Age > 25"或"Name = Subham"就能拿到想要的结果。

但现实中大量数据是非结构化的:电子邮件、短信、社交媒体帖子、音频录音、手写笔记、会议记录。SQL 数据库虽然能存储这些文本和音频却无法理解其中的语义。搜索"car"时,关键词匹配会漏掉写着"automobile"的内容。

Embeddings

机器学习模型可以将非结构化内容转换为 embedding:一组数字构成的向量,用来表征文本的语义。

存储和检索这些向量就是向量数据库的职责,它主要做两件事:高效存储向量,以及快速执行最近邻搜索(语义搜索)。

简单概括:关系型数据库擅长精确的结构化查询;向量数据库擅长对非结构化数据做相似性检索。

向量相似性搜索

向量相似性搜索算法有多种,本文介绍以下四种:余弦相似度搜索、Flat Index、倒排文件索引(IVF)、HNSW(层次化可导航小世界)。

余弦相似度衡量的是两个向量在方向上的接近程度。

取值范围在 -1 到 +1 之间。夹角越小,余弦值越大,相似度越高。方向相同的两个向量夹角为 0,余弦相似度等于 1;互相垂直时夹角为 90 度,余弦相似度为 0;方向完全相反则夹角 180 度,余弦相似度为 -1。

用一个数值例子来说明。取两个句子:

  • S1:"I like backend."
  • S2:"I like frontend"

这里用 one-hot 编码做简化演示。实际场景中,Word2Vec 或 BERT 等模型生成的向量更稠密,语义捕捉能力也更强。

唯一词汇 = [I, like, backend, frontend]

对 S1 和 S2 编码:

  • S1 → [1, 1, 1, 0]
  • S2 → [1, 1, 0, 1]

点积计算:

(1×1)+(1×1)+(1×0)+(0×1)=2

模长计算:

相似度得分:

结果是中等相似度,既不算高也不算低。

Flat Index(暴力搜索)

Flat Index 是最直接的一种向量搜索方式:拿查询向量逐一比对数据集中的每个向量,计算余弦相似度,排序后返回前 K 个结果。没有任何近似或优化手段,因而召回率达到 100%。

具体流程:

  • 取查询向量
  • 初始化空的结果列表
  • 遍历数据集中每一个向量
  • 对每个向量计算与查询向量的余弦相似度
  • (vector, similarity score) 存入结果
  • 按相似度从高到低排序
  • 返回前 K 个最相似的向量

精度最高,但是代价也最高。假如数据集中有 100 万个向量,每次查询都要计算 100 万次距离,速度根本不可接受,所以就出现了倒排文件索引。

倒排文件索引(IVF)

IVF 的核心思路是把整个向量空间切分成若干簇,查询时只在最相关的几个簇里搜索,而不是扫描全部数据。

算法分四个阶段:

第一步,聚类。假设有 100 万个向量,用 k-means 将它们划分为 100 个簇,每个簇对应一个质心向量。

第二步,构建倒排列表。每个簇维护一份属于该簇的向量列表:

C1 → [v1, v2, v3, …]C2 → [v200, v201, …]

第三步,定位最近的簇。给定查询向量 Q,计算 Q 到全部 100 个质心的距离,选出距离最近的若干个簇。选几个簇由 nprobe 参数控制,假设取 5。

Q vs C1Q vs C2…Q vs C100

第四步,在选定簇内搜索。每个簇包含约 1 万个向量,5 个簇加起来只需检索 5 万个向量,相比原来的 100 万缩减了 20 倍。

这就是 IVF 的权衡:用少量的召回率损失换取数量级的速度提升。

层次化可导航小世界(HNSW)

理解 HNSW 之前,需要先掌握两个基础概念:跳表和可导航小世界。

跳表(Skip List)

跳表是一种概率性数据结构,搜索、插入、删除的时间复杂度均为 O(log n)。

它的原理并不复杂:在普通有序链表之上叠加多层快捷指针。搜索时从最高层出发以大步幅向右跳跃;当下一个节点的值超过目标时下降一层继续搜索,每下降一层搜索范围就缩小一截。

以在有序链表中查找 71 为例,规则如下:若 71 等于当前 key,搜索完成;若 71 小于右侧下一个 key,下降一层;若 71 大于或等于右侧下一个 key,向右移动。

普通链表要逐个遍历节点才能定位目标。跳表借助高层索引跨越大量节点,访问路径上的节点数量大幅减少。

可导航小世界(NSW)

NSW 是一种基于图的搜索方法:从某个节点出发,每一步都移动到距离查询点更近的邻居,利用图中的局部捷径快速逼近目标。

过程:随机选择一个入口点。

计算入口点所有邻居到查询节点的距离,移动到距离最近的那个邻居。

重复以上操作,直到当前节点就是距离查询节点最近的位置。

但是NSW 有一个固有缺陷,提前停止问题。搜索可能陷入局部最优:当前节点的所有邻居都不比它离目标更近,搜索于是终止,但全局范围内明明存在更优的节点。这种情况下返回的是次优结果。

图中 2 是次优解,实际上存在更接近目标的节点

层次化可导航小世界(HNSW)


HNSW 把跳表的层次结构和 NSW 的贪心搜索结合在一起。顶层节点稀疏,底层节点稠密——跳表的分层思想;每一层内部通过邻居间的贪心遍历逐步逼近目标——NSW 的搜索策略。

HNSW 算法

  1. 从顶层的入口点开始
  2. 查看当前节点的所有邻居
  3. 移动到距离查询最近的邻居
  4. 重复直到没有更近的邻居(局部最小值)
  5. 下降一层,以当前位置作为新的起点
  6. 重复直到第 0 层
  7. 在第 0 层,使用 ef(搜索宽度)扩展搜索以收集候选项
  8. 从候选项中返回 top-k 结果

整个过程先在高层用少量节点做粗粒度定位,逐层细化搜索范围,到最底层展开精细搜索。高层的大跨度跳转避免了 NSW 中的局部最优陷阱,底层的密集连接保证了最终结果的质量。

总结

三种索引结构各有适用场景。Flat Index 不做任何近似,逐一比对全部向量,精度无损但速度随数据量线性增长,只适合小规模数据集或对召回率有极端要求的场景。IVF 通过 k-means 聚类将向量空间划分为多个分区,查询时仅扫描少数几个簇,用可控的精度损失换来了检索速度的数量级提升;HNSW 则走了一条完全不同的路线——构建多层图结构,高层稀疏连接用于快速定位大致区域,底层密集连接用于精细搜索,兼顾了检索速度和召回质量。

实际工程中,数据规模在几万以下可以直接用 Flat Index;百万级别的数据 IVF 是一个性价比很高的选择;对延迟和召回率都有严格要求的在线服务,HNSW 通常是首选方案。多数向量数据库(Milvus、Qdrant、Weaviate 等)都同时支持这几种索引类型,根据业务需求切换即可。

https://avoid.overfit.cn/post/29081de08b3c4636be3632b0b5f24bbb

by Subham Nayak

目录
相关文章
|
20小时前
|
缓存 人工智能 运维
2026 最新版 OpenClaw 完整汉化教程,Windows 一键安装全流程(包含新安装包)
本教程针对 2026 最新版 OpenClaw 制作,提供集成式一键安装包,内置中文语言文件、运行环境与依赖组件,无需手动配置环境变量、无需输入任何命令代码,从安装到汉化一站式完成,适合所有 Windows 用户,小白也能轻松跟着操作。
|
20小时前
|
人工智能 自然语言处理 安全
2026 最新版 OpenClaw 小白专属安装教程,纯鼠标操作零难度(包含新安装包)
专为零基础新手制作的 OpenClaw 中文版安装教程,2026 新版安装包全程图形化界面,只需点击下一步即可完成安装,自动汉化、自动配置、自动适配,不用懂技术也能顺利安装并正常使用。
|
19小时前
|
人工智能 自然语言处理 安全
2026 最新版 OpenClaw 一站式部署教程,Windows 全功能汉化安装(包含新安装包)
本教程提供 2026 全新编译的 OpenClaw 完整汉化安装包,内置全套运行依赖、中文界面补丁与自动配置脚本,支持全系列 Windows 系统一键安装,无需手动配置环境、无需编写代码,安装后功能完整、界面汉化彻底,可直接用于正常使用与学习。
|
前端开发 UED 开发者
【Flutter前端技术开发专栏】Flutter中的主题与样式主题化
【4月更文挑战第30天】Flutter是一款由谷歌开发的开源移动应用框架,因其高性能和跨平台能力受到开发者青睐。本文聚焦Flutter中的主题与样式主题化,阐述如何通过`ThemeData`定义和设置全局主题,以及如何利用`TextStyle`、`AppBarTheme`和`ButtonTheme`定制文本、AppBar和按钮样式。了解并运用这些知识,能提升应用的统一风格和用户体验,助力Flutter开发。
401 0
【Flutter前端技术开发专栏】Flutter中的主题与样式主题化
|
并行计算 Linux iOS开发
Julia 教程
Julia,一款高性能的开源编程语言,专为科学计算设计,具备动态高级语言特性,速度快,无需解释器。支持多种平台,包括macOS、Windows和Linux等。其特点是小核心、丰富的类型语法、高性能、并行计算优化、C函数直接调用、Unicode支持及元编程工具。常用于数值计算。首个Julia程序示例为打印"Hello World!"。参考链接:[Julia官网](https://julialang.org/)和[Julia中文手册](https://docs.juliacn.com/latest/)。
|
监控 负载均衡 网络协议
Nginx神奇的499竟然不在HTTP响应码标准内?快来了解一下!
Nginx神奇的499竟然不在HTTP响应码标准内?快来了解一下!
593 0
|
IDE Java 开发工具
在kotlin(desktop)中使用libGDX展示一块3D的巧克力
java做游戏,总会让人感觉不太放心,但如果你尝试了libGDX,也许会改变你的看法,它是一款非常优秀的游戏开发引擎,2d场景与3d场景都支持,还支持Windows+Android+iOS+HTML全平台,一起来跟随本文学习一下吧
678 0
在kotlin(desktop)中使用libGDX展示一块3D的巧克力
|
机器学习/深度学习 存储 人工智能
【玩转 GPU】英伟达GPU架构演变
【玩转 GPU】英伟达GPU架构演变
1458 0
【玩转 GPU】英伟达GPU架构演变
|
程序员
P站风格Logo生成器
一个快速生成P站风格的在线工具
5865 1
P站风格Logo生成器

热门文章

最新文章