在 RDS PostgreSQL 中实现 RaBitQ 量化

简介: 本文介绍阿里云RDS PostgreSQL中pgvector的RaBitQ向量量化技术:通过1-bit二值压缩实现32倍索引空间缩减,显著提升千万级向量场景下的存储效率与查询性能,同时保障高召回率,无需引入专用向量数据库。

一、向量检索与 pgvector:数据库里的 AI 能力

近年来,大语言模型和多模态 AI 的普及让向量检索成为基础设施级别的能力。语义搜索、图像检索、推荐系统、RAG(检索增强生成)——这些场景的共同点是:需要将非结构化数据(文本、图像、音频)编码为高维向量,然后在海量向量中快速找到与查询最相似的结果。

不仅是专用的向量数据库,向量检索也逐渐成为传统关系型数据库中的“标配能力”之一。pgvector是一个PostgreSQL的扩展,它基于pg内核提供的Access Method接口实现了IVF-FLAT和HNSW两种向量索引。用户无需引入额外的专用向量数据库,即可在已有的社区版pg中直接使用向量存储和向量搜索的能力。

在阿里云 RDS PostgreSQL 上,pgvector 的能力得到了进一步增强。除了持续跟进开源版本的迭代,我们还针对生产场景的性能、稳定性和可扩展性做了优化。其中,RaBitQ 量化就是我们引入的能力之一——它让 pgvector 在大规模向量场景下的表现得到了提升。


二、pgvector 面临的挑战

pgvector 的HNSW索引在百万级向量规模下完全够用,索引创建和搜索速度表现优异,但当数据量进一步增大,迈向千万级甚至亿级时,向量数据库的常见性能瓶颈在pgvector上会被进一步放大。

  • 存储效率不足。pgvector使用float32数组来表示一条向量。一个 1024 维的 float32 向量占用4096字节。pgvector基于pg内核的shared_buffer实现内存管理,每个页面的大小为固定的8KB,这使得单个页面对高维向量的存储效率是极低的。特别是HNSW索引,在内存资源受限的场景下,在向量搜索阶段会因为Buffer未命中触发大量文件IO,导致查询性能呈现数量级的劣化。
  • 查询延迟的长尾效应。随着索引规模增长,单次查询需要扫描的向量数量增加,P99 延迟的劣化比 P50 更加明显。在高并发场景下,CPU 的浮点计算压力成为瓶颈,查询延迟的稳定性难以保障。
  • 向量插入的性能劣化。pgvector的索引创建过程中依赖pg参数maintenance_work_mem控制内存,在创建HNSW索引时,如果已经构建的图超过了内存限制,后续的图构建会退化到磁盘上,因为创建过程中需要频繁读取图中已经插入的向量来计算距离,这会进一步导致IO瓶颈。索引构建完成后,插入新数据的时候这个问题也会存在。

这些问题的根源在于一个简单的事实:传统索引存储的是完整的浮点向量。无论 IVF-FLAT 还是 HNSW,距离计算都需要读取完整的 d 维 float32 数据并执行 O(d) 次浮点乘加运算。当数据规模增大,对应的计算量和内存消耗都是也是巨大的。下面统计使用pgvector,各个数据集的空间大小。

数据集

数据规模

索引空间

GIST1M

128D1M

654MB

SIFT1M

960D1M

4887MB

dbpedia-openai-1M

1536D1M

7918MB

业务数据集

1024D100M

689GB

向量量化(Vector Quantization)是解决这个问题的有效途径之一。用更少的比特数来表示每个向量,在可接受的精度损失下换取存储和性能的双重收益。


三、向量量化与 RaBitQ

3.1 什么是向量量化

向量量化的核心思想很直接:用更紧凑的方式来表示高维向量。

一个未经量化的 768 维向量,每个维度用 32 位浮点数存储,总共需要 3072 字节。向量量化通过各种编码策略,将这个数字大幅压缩——可能是 8 位整数(每维度 1 字节)、二值比特(每维度 1 比特)、或者是码本索引(每个子向量 1 字节)。

量化后的向量存储占用变小了,但查询时仍然需要估计两个向量之间的距离(欧氏距离或内积)。不同的量化方法有不同的距离估计方式:有些通过查表快速计算,有些通过解析公式近似估计。这个估计过程必然带来精度损失,但好的量化方法能将损失控制在可接受范围内。

pgvector社区已经实现了一些特性。

  • 半精度向量(half vector),使用float16表示向量的每一维,召回率很小,但是压缩比例有限。
  • 二值量化 (binary quantization),实现了 32 倍压缩(float32 → 1 bit/维),但是召回率会有大量损失,无法满足生产要求。

综合上述考量,RaBitQ成为一个更好的选择。我们在pgvector已经支持的索引类型上拓展了框架结构,用来后续支持各种量化方式。

3.2 为什么选择 RaBitQ

RaBitQ(Random Binary Quantization)是一种基于二值化的量化方法。

与其他量化方法相比,RaBitQ 的优势在于

  • 极高的压缩比。使用1bit表示向量的每一维,实现32倍的压缩比。
  • 距离运算的效率提升。将向量距离运算转化为位运算,结合simd一次处理多条向量。
  • 理论的误差界。提供一个可证明的误差范围,向量搜索时可以快速初筛出候选集,再根据误差计算精确距离重排序,确保向量搜索的召回率不会有过多的损失。

四、RaBitQ 在 pgvector 中的工作原理

4.1 RaBitQ 的核心原理

RaBitQ源于论文《RaBitQ: Quantizing High-Dimensional Vectors with a Theoretical Error Bound for Approximate Nearest Neighbor Search》,它利用了高维空间的几何特性。举例来说,在1000维和3维空间的单位球面上随机生成一些单位向量,统计向量第一维的值的分布,会发现高维空间下这些单位向量的取值不是均匀分布的,而是集中在零点附近。

利用这个特性,RaBitQ先把原始向量投影到单位球面上,再通过二值量化表示向量每一维的方向而非具体数值,这样就可以记录到每一条向量的关键信息。实现float32到1bit的向量压缩。在此之前会先对向量做一次随机旋转变换。这个操作将原始向量的信息"均匀打散"到各个维度上,使得每个比特位都能携带有效信息。

在计算距离时,RaBitQ 将原始的内积或欧式距离展开为多个分量。其中绝大部分分量可以在索引创建阶段预计算,或在查询时以常数级别一次性计算(与候选集大小无关)。唯一需要逐向量计算的核心项可以通过SQ4(4bit标量量化)的方式,最终被转化为 1-bit 量化码与 4-bit 查询向量的内积运算,这可以通过位运算 + POPCOUNT的方式快速计算。极大提升了距离运算的效率。

在此基础上,论文证明了估计距离的理论误差界,查询时可以先根据估计距离初筛,再根据理论误差界判断哪些候选向量需要做精确距离计算并参与重排序,保证了查询的召回率。

4.2 pgvector上的 IVF-RaBitQ

IVF-FLAT(倒排文件索引)的工作流程是:先用 K-Means 将向量空间划分为若干 cluster,搜索时先找到距离查询向量最近的 N 个 cluster,然后在这些 cluster 内做精确扫描。

在 RDS PostgreSQL 的 pgvector 实现中,RaBitQ 与 IVF-FLAT 的结合方式如下:

索引构建:

  1. 使用KMeans聚类把原始向量集组织成多个聚类。每个聚类的中心点仍使用原始向量表示。
  2. 初始化RaBitQ信息用来做后续的向量旋转,并写入索引文件。
  3. 以每个聚类的中心点作为RaBitQ的质心,使用RaBitQ对聚类内的向量进行量化,写入索引文件。

向量搜索:

  1. 计算查询向量和各个中心点的距离,选出最近的几个聚类。
  2. 对查询向量进行SQ4量化,在RaBitQ索引上计算估计距离,初步对结果集进行排序。
  3. 根据参数对应误差界,选出部分向量使用原始向量计算精确距离,完成更高精度的重排序。

4.3 pgvector 索引上的 HNSW-RaBiQ

HNSW(分层可导航小世界图)索引将向量组织为多层图:上层为稀疏的"高速公路",下层为稠密的局部邻接图。搜索时从顶层入口逐层向下,在每一层做贪心导航。

HNSW和量化方式结合会有一个问题,如果全程使用RaBitQ上的估计距离来计算和目标向量的距离,这可能会导致在图索引上的搜索方向出现偏差,进一步导致召回率的损失。我们的解决思路如下。

  1. 图的构建(分层和邻接关系建立)基于原始向量。
  2. 在搜索阶段,
  • 在HNSW上层初筛时使用RaBitQ计算估计距离,快速定位到目标向量附近。
  • 在Level 0搜索时,先使用RaBitQ计算估计距离,根据 RaBitQ 的理论误差界,只对估计距离接近的候选向量计算精确距离并进行排序。

五、性能测试:压缩率、延迟与召回率

5.1 测试环境

我们测试pgvector在百万和亿级别数据集下的性能表现,本次测试使用以下环境和数据集。

  • RDS PostgreSQL小版本:RDS PostgreSQL 17 20260330小版本
  • 实例规格: pg.x2.12xlarge.2c
  • pgvector小版本:0.8.0.2
  • 压测工具:ann-benchmark
  • 数据集
  • dbpedia-openai-1M
  • 业务数据集,1024维100M条

5.2 测试结果

5.2.1 dbpedia-openai-1M

我们先使用dbpedia-openai-1M数据集测试内存充足场景下RaBitQ的性能表现。

首先创建索引,然后执行数据集中的查询。对比RaBitQ与社区版本pgvector的性能差异。

索引类型

索引参数

创建时间

索引空间

IVF-FLAT

nlists=1000

95.32s

7820MB

IVF-RaBitQ

nlists=1000

78.72s

248MB

HNSW

m=16,ef_construction=64

281.42s

7918MB

HNSW-RaBitQ

m=16,ef_construction=64

251.97s

510MB

下面是使用ann-benchmark测试得到的recall-qps曲线。

图例说明如下:

  • pgvector,社区版本的HNSW。
  • pgvector_hnsw_rabitq,RDS PostgreSQL的HNSW-RaBitQ索引,引入重排序提升召回率。
  • pgvector_hnsw_rabitq_without_refine,RDS PostgreSQL的HNSW-RaBitQ索引,关闭重排序。
  • pgvector_ivfflat,pgvector社区版本的IVF-FLAT。
  • pgvector_ivfRaBitQ,RDS PostgreSQL的IVF-RaBitQ索引。

5.2.2 1024 维 100M 业务数据集

然后使用业务数据集测试IVF-RaBitQ相较于pgvector社区版本HNSW的性能提升。旨在验证真实生产环境中,IVF-RaBitQ相比HNSW在各个场景下的性能提升。

IVF-RaBitQ

HNSW

索引创建

索引参数

lists=10000

m=16, ef_construction=64

索引创建时间

4h23min17s

4d1h13min47s

索引空间

16GB

689GB

write-only

avg-latency

6.41ms

469.41ms

read-only

查询参数

ivfflat.probes = 100

hnsw.ef_search = 40

top10 avg-latency

342.08 ms

27.65 ms

top100 avg-latency

359.194 ms

1789.22 ms

read-write

write avg-latency

13.42ms

473.54ms

read avg-latency

395.93 ms

1704.64 ms

5.3 小结

  • 在内存充足场景下引入RaBitQ量化后。
  • 同等召回率下,ivf和HNSW相比社区原始版本的查询性能都有所提升。
  • 进行量化后,实现了索引上32倍的压缩比,减少了对内存和存储资源的需求。
  • 在真实业务的大规模数据场景下。
  • 因为内存受限,HNSW在索引创建,数据插入,大结果集查询等场景下都会出现严重的性能劣化。
  • 相比HNSW,IVF-RaBitQ 的优势在于大规模、内存受限场景,而非小结果集的极致低延迟。


六、快速上手:用 SQL 体验 RaBitQ 量化检索

6.1 环境准备

确保你的 RDS PostgreSQL 实例已启用 pgvector 扩展,索引创建和向量搜索与pgvector社区版本语法兼容。

-- 检查 pgvector 版本
SELECT extversion FROM pg_extension WHERE extname = 'vector';

-- 确保 vector 扩展已启用
CREATE EXTENSION IF NOT EXISTS vector;

6.2 创建表并插入数据

-- 创建向量表
CREATE TABLE items (
    id bigserial PRIMARY KEY,
    embedding vector(768)
);

-- 插入示例数据(实际使用中由嵌入模型生成)
INSERT INTO items (embedding)
SELECT array_agg(random())::vector(768)
FROM generate_series(1, 100000);

6.3 创建 RaBitQ 量化的 IVF-FLAT 索引

-- 创建 RaBitQ 量化的 IVF-FLAT 索引
-- lists 参数控制 cluster 数量,通常设为数据量的平方根
CREATE INDEX ON items
USING ivfflat (embedding rabitq_vector_cosine_ops)
WITH (lists = 100);

6.4 创建 RaBitQ 量化的 HNSW 索引

CREATE INDEX ON items
USING hnsw (embedding rabitq_vector_cosine_ops)
WITH (m = 16, ef_construction = 64);

6.5 执行量化搜索查询

-- 设置搜索参数
SET ivfflat.probes = 10;    -- IVF-FLAT 搜索的 cluster 数量
-- SET HNSW.ef_search = 64; -- HNSW 搜索的候选集数量

-- 执行相似度搜索(余弦距离)
SELECT id, embedding <=> '[0.1, 0.2, ...]' AS distance
FROM items
ORDER BY embedding <=> '[0.1, 0.2, ...]'
LIMIT 10;


结语

RaBitQ 量化的引入,让 RDS PostgreSQL 上的 pgvector 在保持 PostgreSQL 生态优势的同时,显著提升了大规模向量检索的效率和可扩展性。无需引入额外的向量数据库,无需复杂的运维配置,仅通过一个索引参数即可开启高倍压缩和检索加速。

对于正在使用或计划在阿里云 RDS PostgreSQL 上处理向量检索的团队,RaBitQ 是一个值得尝试的选项。


来源  |  阿里云开发者公众号

作者  |  庭章

相关文章
|
1天前
|
缓存 人工智能 安全
你不知道的 Agent:原理、架构与工程实践
文章内容基于作者个人技术实践与独立思考,旨在分享经验,仅代表个人观点。
|
1天前
|
人工智能 测试技术 开发者
Harness Engineering实践,做了一个平台让AI一晚上自动评测和优化你的系统
文章内容基于作者个人技术实践与独立思考,旨在分享经验,仅代表个人观点。
|
1天前
|
人工智能 前端开发 Shell
一个文件让 AI Coding 效率翻倍:AGENTS.md 实践指南
文章内容基于作者个人技术实践与独立思考,旨在分享经验,仅代表个人观点。
一个文件让 AI Coding 效率翻倍:AGENTS.md 实践指南
|
1月前
|
Oracle Java 关系型数据库
在Linux环境安装JDK21
本文详细介绍了在Linux系统中下载并安装JDK 21的完整流程:从Oracle官网下载JDK 21 Linux版tar.gz包,删除旧版JDK 8(可选),解压安装,修改`/etc/profile`配置`JAVA_HOME`与`PATH`,最后通过`source`生效并验证`java -version`。同时提供JDK历史版本下载指引。
在Linux环境安装JDK21
|
14天前
|
人工智能 JSON 监控
Qoder CLI + Harness Engineering 实战:构建 7×24h 无人值守用户反馈自动处理系统
Qoder推出7×24小时无人值守用户反馈自动处理系统,基于Qoder CLI构建四大模块:智能分类、语义聚类、日志根因分析与自动修复。AI自动完成问题识别、归并、定位及代码生成,人工仅需终审Code Review,处理时效从30分钟缩短至2分钟。
Qoder CLI + Harness Engineering 实战:构建 7×24h 无人值守用户反馈自动处理系统
|
20天前
|
弹性计算 人工智能 搜索推荐
一键部署 Hermes Agent 自进化智能体——阿里云纯免费体验Hermes,基于ECS、百炼和计算巢服务
Hermes Agent 是 Nous Research 开源的自进化智能体框架,具备跨会话持久记忆、自主学习闭环与多平台统一接入能力。支持本地私有部署,数据不出域。阿里云提供 ECS + 百炼 + 计算巢一键免费部署方案,开箱即用。
291 1
|
25天前
|
人工智能 移动开发 安全
3. OpenClaw本地AI建站教程:部署、生成、调试、上线,全程清晰可落地
本教程教你用本地离线AI工具OpenClaw,零代码快速搭建企业静态网站:从一键部署、文字描述需求、AI生成HTML/CSS/JS源码,到本地调试、自由修改及上线部署,全程实操清晰,30分钟即可完成,安全可控、高度定制。(239字)
|
7月前
|
缓存 JSON 前端开发
淘宝 item_get_pro 接口实战:SKU 图 / 文 / 价 / 规格一键获取
本文详解如何通过淘宝开放平台`item_get_pro`接口高效获取电商SKU核心数据,涵盖图片、价格、属性等字段的精准匹配方法,并分享缓存、重试、校验三大实战技巧,附Python调用示例,助你快速解决SKU信息混乱难题。
|
11月前
|
监控 JavaScript 开发工具
【HarmonyOS 5】鸿蒙中@State的原理详解
@State 是 HarmonyOS ArkTS 框架中用于管理组件状态的核心装饰器,其核心作用是实现数据驱动 UI 的响应式编程模式。通过将变量标记为 @State,开发者可以确保当状态值发生变化时,依赖该状态的 UI 组件会自动重新渲染,从而保持数据与界面的实时同步。 @State 是 HarmonyOS ArkTS 实现响应式编程的大基础核心,可以说整个V1和V2都是围绕它来进行组合使用。
432 0