💡阅读指南

上一节学会了通过 API 获取 Embedding 向量——给文字贴上了"语义坐标"。但有了向量之后呢?

假设知识库里有成千上万条文档,每条都变成了高维向量。用户提一个问题,需要从海量向量中找出最相关的几条。一个个比对效率极低。这一节解决的就是这个核心问题。


5.1 为什么需要向量数据库

从一个真实场景说起。

一个现实的难题

假设做一个企业知识库问答系统。先看数据规模: - 知识库有1000份文档 - 每份文档平均5页,切分成100个片段(Chunk) - 算下来:10万个文档片段 - 每个片段都转成了1536维向量

现在用户问:"年假怎么申请?"

系统需要做什么? 1. 把这个问题也转成向量 2. 在10万个向量中找到最相似的5个 3. 把这5个片段交给大模型,让它生成答案

第2步是关键。怎么在10万个向量里快速找到最相似的那5个?

朴素方法的困境

最直接的想法是什么?"暴力搜索"——一个个比对。

Python
# 伪代码:朴素的相似度搜索
question_vec = get_embedding("年假怎么申请?")

similarities = []
for i, doc_vec in enumerate(all_100k_vectors):
    # 计算余弦相似度
    sim = cosine_similarity(question_vec, doc_vec)
    similarities.append((sim, i))

# 排序,取前5个
top_5 = sorted(similarities, reverse=True)[:5]

这段代码有什么问题?

算笔账: - 要计算10万次向量点积(每次都是1536维的计算) - 还要对10万个结果排序 - 单次查询耗时(预估):约2-3秒

2-3秒什么概念?想想这些场景:

  • 用户会觉得卡顿(现在的人哪有这个耐心)
  • 100个用户同时问问题?系统直接崩溃
  • 如果用户增长到1万个和10万个呢?

在真实的生产环境中,这个问题会被成倍放大: - [×] 100万条文档 → 30秒查询时间 - [×] 1000万条文档 → 5分钟查询时间
- [×] 用户等不了,系统也撑不住

这就是为什么需要向量数据库。

5.2 向量数据库的价值

向量数据库做了件很聪明的事:它不会每次都傻傻地遍历所有向量,而是提前把向量组织成特殊的数据结构,让检索可以"跳着走"。

打个比方。

朴素搜索 = 在字典里逐页翻查

要找"Apple"这个词 从第1页开始,一页页翻,直到找到 结果:翻了100页才找到

向量数据库 = 用索引和目录

要找"Apple" 1. 看首字母索引 → 直接跳到"A"开头的部分 2. 看第二个字母 → 跳到"Ap" 3. 看第三个字母 → 定位到"App" 4. 找到"Apple" 翻页次数:只需3-5次

这不是快一点点,是快到离谱。向量数据库的核心优势就在这: - [√] 速度快:毫秒级响应,支持高并发 - [√] 可扩展:百万、千万、亿级数据都能处理
- [√] 准确率高:虽然是"近似搜索",但准确率通常在99%以上 - [√] 工程化:支持增删改查、批量操作、分布式部署


5.3 向量数据库的工作原理

向量数据库的核心技术叫近似最近邻搜索(Approximate Nearest Neighbor,ANN)。名字听起来有点拗口,但思想很简单。

核心思想:空间分区

最好理解的方法就是"空间分区"——把向量空间划分成多个区域,查询时只需要在最相关的几个区域里搜索。

用生活中的例子来理解。

5.4 类比:在体育场找人

想象在一个能容纳10万人的体育场里,要随便找到一位穿红色衣服的观众。怎么找?

暴力搜索

从第1排第1座开始,按座位顺序一个个检查每个人的衣服颜色, 直到终于遇到一位穿红衣服的观众。 如果平均检查每个人需要 1 秒,想靠这种方式查一遍,这得看运气,最长需要30个小时左右。

分区搜索(IVF 的思路)

  1. 先把体育场划分成100个看台区域;
  2. 快速扫一眼每个区域的大致颜色分布, 找出"红衣服明显更多"的3个区域;
  3. 只在这3个区域里逐排逐座细查。 这样只需要仔细检查几千个人,耗时从"几个小时"降到"几十分钟"。

图搜索(HNSW 的思路)

  1. 从体育场入口的引导员开始打听;
  2. 引导员说:"我刚才看到A区红衣服比较多,去A区问问";
  3. 到了A区后,当地引导员再指"A3看台那一片红衣服最多";
  4. 走到A3,看台管理员直接指"就在这边第5排";
  5. 几分钟内,就锁定到了那一小撮红衣服观众中的一位。 整个过程只和少数几个"关键节点"打了交道,而不是亲自看过10万人。

向量数据库就是用类似的思想,把高维空间中的向量组织起来。下面看三种主流的索引算法。了解即可。

5.5 IVF(倒排文件索引)

核心思想:聚类 + 倒排

第1步:聚类

  • 使用 K-Means 算法,把所有向量按距离聚成 N 个簇(比如 N=1000)
  • 算法会找到 N 个“簇中心”,每个簇内的向量距离都比较近
  • 比如:把 10 万个点分成 1000 组,语义相近的向量会聚在一起

图示:

code
向量空间(简化为2D平面):

          簇3                     簇1
         ★                       ●
      ★  ★  ★               ● ●
    ★  ★中心 ★              ●  ●中心 ●
      ★  ★                   ● ●
        ★                       ●


            簇4                簇2
           ■                  ▲
        ■  ■                ▲ ▲
      ■  ■中心 ■           ▲  ▲中心 ▲
        ■  ■                ▲ ▲
           ■                  ▲

解读: - 每个符号(●▲■★)代表一个向量 - 同一种符号 = 同一个簇(逻辑分组) - "中心" = 簇中心,位于该簇所有向量的几何中心 - 语义相近的向量聚在一起,距离远的分开

第2步:查询

  • 计算查询向量到各个簇中心的距离
  • 找到距离最近的 K 个簇(比如 K=10)
  • 只在这 K 个簇里搜索,而不是搜索全部 10 万个向量
  • 返回最相似的结果

用一个示例来理解。假设要找"Python 语言怎么样?"的相关内容:

步骤1:计算查询向量到所有1000个簇中心的距离 簇1(编程语言): 距离 = 0.2 ← 最近 簇2(美食菜谱): 距离 = 0.9 簇3(旅游攻略): 趻离 = 0.85 ... 簇15(技术教程): 距离 = 0.18 ← 最近 ...

步骤2:选择最近的10个簇 簇15(技术教程)、簇1(编程语言)、簇8(软件开发)... 这些簇共有 1000 个向量

步骤3:只在这 1000 个向量中搜索 找到:

  • “Python 入门教程:基础语法” (距离 = 0.10)
  • “Python 与其他语言对比” (距离 = 0.13)
  • “Python 应用场景分析” (距离 = 0.16)

结果:返回这 3 条相关内容

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

核心思想:多层图结构 + 贪婪搜索

HNSW把向量组织成一个多层的图结构。

整体结构

code
第2层(稀疏):只有少数节点
    A --------------------------- D

第1层(中等):节点增多
    A ------- B ------- D
              |         |
              C ------- E

第0层(密集):包含所有节点
    A - B - D - F
    |   |   |   |
    H - C - E - G

查询流程

  • 从顶层开始,在每一层找到离查询向量最近的点
  • 逐层下降,每一层都更精确地逃近目标
  • 最终在底层找到最相似的向量

查找示例

假设要找"Python 数据分析"的相关内容

步骤1:第2层(稀疏,只有10个点) 当前在入口点 A

  • 计算查询向量“Python 数据分析”到节点的距离:
    • 到 A(前端开发): 0.8
    • 到 D(后端框架): 0.5
  • D 更近 → 跳到 D

步骤2:第1层(中等,有50个点) 当前在点 D - 计算查询向量到 D 的邻居的距离: - 到 A(前端开发): 0.8 - 到 B(Web开发): 0.4 - 到 E(Python教程): 0.3 - E 更近 → 跳到 E

步骤3:第0层(密集,所有100个点) 当前在点 E
- 计算查询向量到 E 的邻居的距离: - 到 C(Java开发): 0.6 - 到 D(后端框架): 0.5 - 到 G(Python数据分析教程): 0.15 - G 更近 → 跳到 G - 计算查询向量到 G 的邻居的距离: - 到 E(Python教程): 0.3 - 到 F(Python编程): 0.4 - 到 H(NumPy库): 0.2 - G 自己(0.15)比所有邻居都近 → 停止

结果:找到 G - "Python数据分析教程"

上述流程最终能找到最相似的"邻近"向量,但不只想找1个"最"相近的,而是想找多个相近的(Top-K)向量。 比如如果要找 Top-5 最相似的结果,那按照上述的流程做5遍吗?并不是。真正的方法如下:

  • 搜索过程中维护一个“候选集”(比如保留搜索过的前10个最近的点)
  • 搜索结束后,从候选集中返回距离最近的5个
📌说明

向量怎么分层?

上述图的查找方法,是建立在分层的基础上。一堆向量是怎么分层的? 有兴趣可以阅读下。

其实很简单,完全是随机分层的。

HNSW 建索引时,每个向量都会随机分配一个“层级”: - 每个向量插入时,随机决定它的“最高层级”(就像抛硬币) - 大多数向量只到第0层,少数能到第1层,更少数到第2层 - 就像金字塔:底层人多,越往上人越少

具体例子:

  • 向量 A:随机到“第2层” → 在第0、第1、第2层都有(作为“快速跳转点”)
  • 向量 B:随机到“第1层” → 在第0、第1层有,第2层没有
  • 向量 C:随机到“第0层” → 只在第0层(大多数向量都这样)

为什么要随机?

  • 随机分层能保证图结构的平衡性,避免“热点聚集”
  • 不需要复杂的计算,构建索引更快
  • 实践证明:随机分层的效果非常好!

这样设计的好处:

  • 顶层节点少 → 搜索快速定位大致区域
  • 底层节点全 → 精确找到最相似的

5.7 ■ 学点英语

中文 English 音标 说明
近似近邻 Approximate Nearest Neighbor (ANN) /əˈprɑːksɪmət ˈnɪərəst ˈneɪbər/ 通过索引结构牺牲少量精度换取极快检索速度的算法
精确近邻 K-Nearest Neighbor (KNN) /keɪ ˈnɪərəst ˈneɪbər/ 遍历全部数据确保返回最精确的Top-K结果
倒排文件索引 Inverted File Index (IVF) /ɪnˈvɜːrtɪd faɪl ˈɪndeks/ 通过聚类将向量空间分区,只搜索最近簇的索引方法
分层可导航小世界图 Hierarchical Navigable Small World (HNSW) /ˌhaɪəˈrɑːrkɪkl ˈnævɪɡəbl smɔːl wɜːrld/ 基于多层图结构的近似搜索算法,查询极快
Voronoi 单元 Voronoi Cell /vəˈroʊnɔɪ sel/ IVF聚类后向量空间被划分成的区域,查询时搜索最近单元

5.8 ■ 思考帧

💬
本节包含互动练习 #256

该练习为课程站点内嵌互动题,未收录于本地离线包;如需作答请回到线上课程对应课时。

💬
本节包含互动练习 #257

该练习为课程站点内嵌互动题,未收录于本地离线包;如需作答请回到线上课程对应课时。

💬
本节包含互动练习 #258

该练习为课程站点内嵌互动题,未收录于本地离线包;如需作答请回到线上课程对应课时。

💬
本节包含互动练习 #259

该练习为课程站点内嵌互动题,未收录于本地离线包;如需作答请回到线上课程对应课时。

💬
本节包含互动练习 #260

该练习为课程站点内嵌互动题,未收录于本地离线包;如需作答请回到线上课程对应课时。

💬
本节包含互动练习 #261

该练习为课程站点内嵌互动题,未收录于本地离线包;如需作答请回到线上课程对应课时。