pg_vectorsearch 是一个用于 PostgreSQL 的高性能近似最近邻(approximate nearest neighbor,ANN)搜索扩展,目前处于 alpha 状态,仅用于测试而非生产环境;预发布版本之间可能无法直接升级,需删除并重建该扩展及其索引,已知问题见 changelog。它提供 PRISM 索引(PRISM index),采用 IVF 风格并支持分层路由,可处理 1 亿以上向量;同时还引入 RaBitQ 量化(RaBitQ quantization),为两阶段搜索提供理论误差边界。
正文
一个用于高性能近似最近邻(ANN)搜索的 PostgreSQL 扩展。
状态:alpha。 仅供测试,勿用于生产。预发布版本之间可能无法升级;请做好删除并重建扩展及其索引的准备。已知问题详见更新日志。
- PRISM 索引(支持 1 亿以上向量)——IVF 风格,带分层路由
- RaBitQ 量化——为两阶段搜索提供理论误差界限
- SIMD 优化的距离计算(AVX2、AVX512、NEON)
- 动态更新——支持插入、更新和删除,可通过
prism_rebalance拆分倒排列表(参见维护) - 兼容 pgvector——可直接为已有的
vector和halfvec列建索引(参见已有的 pgvector 表)
PRISM 索引
PRISM(Partitioned Routing Index for Similarity Matching,面向相似度匹配的分区路由索引)是一种 PostgreSQL 原生的索引访问方法,概念上类似于 pgvector 的 IVFFlat,但它围绕最先进的量化、路由和分区技术构建。它用 C 实现,以获得高性能并与 PostgreSQL 无缝集成。
结果是:无论查询还是建索引,它都比 pgvector 的 IVFFlat 和 HNSW 快得多。事实上,在 1 亿向量的数据集上,与基于图的 HNSW 相比,PRISM 在同等召回率下速度更快,而且是在内存仅为 HNSW 四分之一的实例上达成的。
为了实现这一性能,PRISM 使用分层质心树将向量划分为簇,并依赖 PostgreSQL 的缓冲缓存将该树保留在内存中保持热度。向量经过 RaBitQ 量化后存入倒排列表,页面布局针对 SIMD 距离计算做了优化。RaBitQ 编码带有误差界限,使搜索能排除那些不可能是最近邻的向量,因此需要对表中存储的全精度向量做重排序(rerank)的数量大大减少。
查询流程:
- 遍历质心树,找到最近的簇(缓冲缓存)
- 扫描倒排列表获取候选向量(缓冲缓存,异步 I/O)
- RaBitQ 两阶段过滤:估计 → 误差界限 → 重排序
- 从堆中进行全精度重排序
- 返回 k 个最近邻
详细架构参见 docs/architecture.md。
使用方法
请先安装扩展;参见构建。
有两种使用 PRISM 索引的方式,请选择与你的向量存储情况相匹配的一种:
- 原生类型。 如果从头开始,或者没有使用 pgvector?可以把向量存入
pg_vectorsearch自带的vec32(float32)或vec16(float16)列。不需要其他扩展。 - 已有的 pgvector 表。 如果已经有
vector或halfvec列?在 pgvector 之外再安装pg_vectorsearch,并直接在这些列上建 PRISM 索引。你的表和查询都无需改动。
两种方式建的是同一种索引,使用相同的操作符(<->、<#>、<=>)和相同的调优参数。
原生类型
CREATE EXTENSION pg_vectorsearch;
-- PLAIN 表示向量内联存储。EXTERNAL(默认)会在值超过约 2 kB 时进行 TOAST 存储,之后重排序要多一次 planner 未计入开销的读取。
CREATE TABLE items (
id serial PRIMARY KEY,
embedding vec32(3) STORAGE PLAIN
);
-- 先导入数据;索引大小在 CREATE INDEX 时按行数确定。
-- 500 行就足以让 planner 使用该索引。
INSERT INTO items (embedding)
SELECT ARRAY[i::real, (i % 7)::real, (i % 5)::real]::vec32
FROM generate_series(1, 1000) i;
-- 内积或余弦距离请参见下面的操作符类。
CREATE INDEX ON items USING prism (embedding vec32_l2_ops);
-- 0 表示自动(约 0.95 召回率)。调高可提升召回率,调低可提速。
SET prism.nprobe = 40;
SELECT * FROM items
ORDER BY embedding <-> '[3,1,2]'
LIMIT 5;
如果改用 vec16 代替 vec32,向量在表中占用的空间可减半,并搭配对应的 vec16_*操作符类。
已有的 pgvector 表
如果你已经有含 pgvector vector 或 halfvec 列的表,可以直接在其上建 PRISM 索引。表和查询都无需任何改动。vec32 和 vec16 与 pgvector 的 vector 和 halfvec 二进制兼容,只是名称不同,因此两个扩展可以并排安装,甚至在相同 schema 下共存。
-- 这是你已有的表,为了让示例能独立运行而包含在此。
CREATE EXTENSION vector;
CREATE TABLE documents (
id bigserial PRIMARY KEY,
body text,
embedding vector(384)
);
CREATE INDEX documents_embedding_hnsw
ON documents USING hnsw (embedding vector_l2_ops);
-- 在 pgvector 之外安装 pg_vectorsearch,并在已有列上建索引。
-- 该列不会被重写或复制。
CREATE EXTENSION pg_vectorsearch;
CREATE INDEX documents_embedding_prism
ON documents USING prism (embedding vec32_l2_ops);
-- 你的查询照旧可用。PRISM 通常更快,因此在两个索引同时存在时,
-- planner 应优先选择它而不是 HNSW 索引。可用 EXPLAIN 验证:
EXPLAIN (COSTS OFF)
SELECT id, body
FROM documents
ORDER BY embedding <-> (SELECT embedding FROM documents WHERE id = 42)
LIMIT 10;
-- Limit
-- InitPlan 1
-- -> Index Scan using documents_pkey on documents documents_1
-- Index Cond: (id = 42)
-- -> Index Scan using documents_embedding_prism on documents
-- Order By: (embedding <-> (InitPlan 1).col1)
-- 确认无误后,删除 HNSW 索引。
DROP INDEX documents_embedding_hnsw;
使用与你的 HNSW 索引相同距离度量的 PRISM 操作符类。
操作符类
为你的距离度量和列类型选择操作符类。L2 是默认选项。
| 距离度量 | 操作符 | vec32 / vector | vec16 / halfvec |
| --- | --- | --- | --- |
| L2 | <-> | vec32_l2_ops | vec16_l2_ops |
| 内积 | <#> | vec32_ip_ops | vec16_ip_ops |
| 余弦 | <=> | vec32_cosine_ops | vec16_cosine_ops |
替换 HNSW 索引时,pgvector 的 vector_<metric>_ops 对应 vec32_<metric>_ops,halfvec_<metric>_ops 对应 vec16_<metric>_ops。
调优
默认值基于大规模基准测试调优;大多数部署只需调整 prism.nprobe。所有索引参数、GUC、它们的权衡以及何时适合修改,参见调优指南。
维护
插入操作会把向量追加到其路由到的倒排列表中,因此列表会随数据写入而增长,且不会自动分裂。除了 REINDEX,prism_rebalance 过程可就地拆分过大的列表。其工作原理及当前限制参见维护指南。
构建
要求:
- PostgreSQL 18+(含开发头文件)
- GNU C11 编译器(GCC 11+ 或 Clang 14+)
- Meson 构建系统
可选:CBLAS,用于加速 RaBitQ 编码。参见开发。
发布构建
meson setup builddir --buildtype=release
构建并安装到 PostgreSQL
meson install -C builddir
构建选项参见开发指南。
文档
参考
研究
- RaBitQ —— 带理论误差界限的二值量化(SIGMOD 2024)
- SPFresh —— 用于增量更新的 LIRE 协议(SOSP 2023)
- SPANN —— 采用边界复制的十亿级 ANN(NeurIPS 2021)
- ScaNN for AlloyDB —— 分层聚类(Google)
相关项目
- pgvector —— PostgreSQL 的向量类型与操作符
- pgvectorscale —— 基于 DiskANN 的 PostgreSQL 向量索引
许可证
评论
讨论开场被官方“更快、更省内存”的 PRISM 索引宣传吸引,但实际气氛很快转为审视落地条件。少数人为低内存向量索引与竞争利好叫好,较多人则质疑过滤、托管 PostgreSQL 支持、PostgreSQL 18 要求、维度上限和基准测试缺失等现实门槛;分歧主轴是性能叙事与生产可用性之间的落差。
看好低内存向量索引的竞争与降本潜力
- 正在使用 VectorChord 的开发者表示,配合高速 NVMe 磁盘已把 Postgres 成本降低一半,因此欢迎更多低 RAM 向量索引工具入局;内存涨价带来的压力正促使社区利用现代 NVMe 的速度。(少数人) > 我正用 VectorChord,配合高速磁盘把 Postgres 成本砍半,很高兴看到低 RAM 向量索引工具出现竞争。(@EgregiousCube)
指出托管 PostgreSQL 与版本升级要求阻碍采用
- 如果云厂商不在托管 PostgreSQL 中提供该扩展,依赖托管服务的团队基本无法使用;它又要求 PostgreSQL 18、仍属刚发布的 alpha,未进入 Azure 等超大规模云服务商托管 PostgreSQL 的允许扩展列表,也尚未在 Timescale 之外的生产环境经受检验,旧版自建迁移成本过高,短期难以落地。(较多人)
质疑过滤、租户隔离与维度上限等能力缺口
- 过滤目前只支持后过滤,有人质疑这会让租户、用户或权限范围隔离难以高效实现;同时 PRISM 的向量维度上限为 1968,原有更高维的 HNSW 索引暂时无法直接替换。(较多人)
认为应先公开 QPS 与召回率等严谨基准
- 有人质疑官方把性能结论讲得太像营销,认为如果真快,就应该首先给出 QPS 与精度/召回率,而不是只展示延迟和内存节省。(少数人) > 既然主打快,就该先把 QPS 和精度/召回率放出来。(@esafak)
追问与 pgvectorscale、pg_search、RoarGraph 等方案的差异
- 多位评论者接连把它与 pgvectorscale、ParadeDB 的 pg_search、RoarGraph 等现有向量或搜索方案放在一起比较,想先确认定位与替代关系,而不是只听单一宣传。(较多人)
有价值的补充
- 仓库封面图被指完全致敬 Pink Floyd 的《The Dark Side of the Moon》,索引名 PRISM 也被玩成了「Dark Side of the PRISM」的谐音梗。