首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >向量索引预热(prewarm)原理

向量索引预热(prewarm)原理

作者头像
用户4035096
发布2026-07-09 19:45:10
发布2026-07-09 19:45:10
140
举报

向量索引预热(prewarm)原理

当从PG数据库访问数据时, shared buffer中没有被访问的数据, 需要从数据文件所在的存储(例如磁盘)中读取数据块, 加载到shared buffer中, 以便下一次加速访问.

数据库运行一段时间后, 通常shared_buffer里面已经存在大量热数据(经常被访问的数据), 性能会比较平稳.

但是, 一旦数据库重启, shared_buffer将被清空, 如果业务高峰期发生主动重启或被动重启(例如oom、HA等原因), 可能出现严重的性能下降/抖动, 甚至触发数据库雪崩效应.

为了解决这个问题, PG提供了数据预热插件pg_prewarm, 结合pg_buffercache(可通过这个插件定期将buffer 内的数据块ID存到表中), 在应用程序访问数据库之前, 先根据存储的数据块ID预热到shared buffer中. 杜绝抖动问题.

向量数据库呢?

向量索引也可以预热, 但是向量索引通常都比较大, 容易把shared buffer打满.

实际上没有必要把整个索引都预热进来, 也能保障性能. 为什么呢?

因为向量索引通常是层次结构的, 例如rabitq+ivf的向量索引, 通常是有多层的. hnsw向量索引也是多层结构(越靠近搜索开端的层, 越稀疏, 就像地图, 最稀疏层可能只包含国家级别的数据, 然后逐层细化.).

vectorchord提供了向量索引预热接口函数, 同时考虑到向量索引的层级结构, 只需要把靠近搜索端的某些层级加热到shared buffer即可提升访问性能.

vectorchord 向量索引预热例子

对于向量索引,索引大小通常远大于内存大小。向量索引的设计使得索引数据被分成两部分:一小部分是热数据,另一部分是冷数据。向量索引只需要内存中的热数据即可实现合理的性能。因此,存在一个专门的预热函数,它只将索引的热数据加载到内存中。

rabitq+ivf的例子

代码语言:javascript
复制
SELECT vchordrq_prewarm('items_embedding_idx');  

即使索引大小远大于内存大小,它也能很好地运行。

预热原理

vchordrq_prewarmvchordg_prewarm是VectorChord中两种不同索引访问方法的预热函数,它们通过将索引的热数据部分加载到内存中来提升查询性能。

函数接口差异

两个预热函数在PostgreSQL中的接口定义有所不同 :

  • vchordrq_prewarm(regclass, integer default 0):接受索引关系和高度参数
  • vchordg_prewarm(regclass):只接受索引关系参数

实现原理

两个函数都遵循相同的验证和调用模式 :

  1. 索引验证:验证传入的关系ID是否为对应类型的有效索引
  2. 关系打开:使用AccessShareLock打开索引关系
  3. 操作族获取:获取索引的操作族信息以确定向量类型和距离函数
  4. 算法调用:调用相应的底层预热算法

底层算法调用

vchordrq预热算法

vchordrq_prewarm根据向量类型和距离函数分发到不同的算法实现 :

  • 支持VectorKind::Vecf32VectorKind::Vecf16两种向量类型
  • 支持DistanceKind::L2SDistanceKind::Dot两种距离函数
  • 使用MakeH0PlainPrefetcher作为预取器
  • 调用vchordrq::prewarm()函数,传入索引、高度参数和预取器
vchordg预热算法

vchordg_prewarm使用类似的分发模式但不需要高度参数 :

  • 支持相同的向量类型和距离函数组合
  • 直接调用vchordg::prewarm()函数,只传入索引参数

预热策略差异

基于背景信息中提到的热/冷数据分离设计,两种索引方法采用不同的预热策略:

  • vchordrq:基于RaBitQ + IVF算法,使用高度参数控制预热的层级深度,只加载指定高度以上的热数据部分
  • vchordg:基于图遍历算法,预热整个图结构的关键连接部分,不需要层级控制

Notes

两个预热函数都通过crates/vchordg/src/lib.rs和对应的vchordrq crate中的prewarm模块实现具体的预热逻辑 。这些函数在基准测试脚本中被调用以优化查询性能 。

向量索引层级原理

在vchordrq索引中,高度(height)是层次化IVF结构中的核心概念,定义在MetaTuple的存储结构中 。

高度的存储定义

高度信息存储在索引的元数据结构中:

  • height_of_root字段定义了整个索引树的根节点高度
  • MetaTupleHeader结构体中作为u32类型存储

层次化索引结构

vchordrq使用多层聚类结构,每一层都有对应的高度值:

高度在构建过程中的确定

在索引构建时,高度通过层次化聚类过程确定 :

  1. 内部构建:通过k-means聚类逐层构建,每层对应一个高度级别
  2. 外部构建:通过DFS遍历计算每个节点的高度

预热中的高度使用

在搜索和预热过程中,高度参数控制遍历深度:

  • 搜索时验证height_of_root与探针数量的匹配
  • 预热函数接受高度参数来限制加载的层级范围
  • 通过step函数逐层遍历,从根节点向下到指定高度

高度与热数据的关系

预热过程中,高度参数决定了哪些层级被视为"热数据":

  • 高度越高的层级包含的数据越少,访问频率越高
  • 预热时只加载高于指定高度的层级,避免加载大量的叶子节点数据
  • 这种设计符合IVF算法的特性:上层质心用于快速定位,下层数据用于精确计算

Notes

高度概念在vchordrq中是层次化IVF结构的核心,与传统B树索引的高度概念类似但应用于向量聚类场景。外部构建模式还支持从用户提供的层次结构表中构建索引,此时高度通过树遍历算法计算得出。

参考

https://docs.vectorchord.ai/vectorchord/usage/prewarm.html

https://deepwiki.com/search/vchordrqprewarmvchordgprewarm_f3958251-a8d8-41b8-b8ea-96c27128f5ff

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-11-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 digoal德哥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 向量索引预热(prewarm)原理
  • vectorchord 向量索引预热例子
  • 预热原理
    • 函数接口差异
    • 实现原理
    • 底层算法调用
      • vchordrq预热算法
      • vchordg预热算法
    • 预热策略差异
    • Notes
    • 向量索引层级原理
    • 高度的存储定义
    • 层次化索引结构
    • 高度在构建过程中的确定
    • 预热中的高度使用
    • 高度与热数据的关系
    • Notes
  • 参考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档