跳到主要内容

向量操作

PostgreSQL 使用 pgvector 扩展存储和检索向量。通用读写用法见向量类型映射,查询用法见KNN 近邻排序距离范围过滤

向量类型映射

vector(3) 保存三维向量,不是 PostgreSQL 数组。先启用扩展,再定义字段:

CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE vector_item (
id BIGINT PRIMARY KEY,
embedding vector(3)
);

该字段使用 List<Float>PgVectorTypeHandler,配置见向量类型处理器。写入和查询均传三维向量,无需先转成 PGobject

二进制向量使用 BIT(n) 字段,查询参数使用类型为 bitPGobject,不要套用浮点向量处理器:

PGobject target = new PGobject();
target.setType("bit");
target.setValue("11110000"); // 对应 BIT(8)

距离范围过滤

支持 L2、余弦、内积,以及 BIT(n) 的 Hamming、Jaccard 距离过滤;pgvector 不提供 BM25 评分。

pgvector 的 <=> 返回余弦距离,等于 1 - 余弦相似度。要查相似度大于 0.8 的记录,距离阈值应传 0.2,而不是 0.8

List<VectorItem> rows = lambda.query(VectorItem.class)
.vectorByCosine(VectorItem::getEmbedding, target, 0.2)
.queryForList();

其中 target 是目标向量;生成的条件为 embedding <=> ? < 0.2orderByCosine 按距离升序排列,相似度高的记录在前。

按内积查询

pgvector 的 <#> 返回负内积orderByIP 按负内积升序排列,因此实际内积大的记录在前。

要查内积大于 0.8 的记录,阈值应传 -0.8

List<VectorItem> rows = lambda.query(VectorItem.class)
.vectorByIP(VectorItem::getEmbedding, target, -0.8)
.queryForList();

生成的条件为 embedding <#> ? < -0.8

KNN 近邻排序

BIT(n) 使用 orderByHammingorderByJaccard 按距离升序排列;浮点向量使用下表的三种方式。不支持 orderByBM25

索引需要与查询使用的距离匹配:

构造器 API 排序pgvector 运算符索引运算符类
orderByL2<->vector_l2_ops
orderByCosine<=>vector_cosine_ops
orderByIP<#>vector_ip_ops

例如使用 orderByCosine 查询最近的 10 条记录时,配套的 HNSW 索引为:

CREATE INDEX vector_item_cosine_idx
ON vector_item USING hnsw (embedding vector_cosine_ops);

L2 索引不能替代余弦索引。索引近邻查询需要按距离升序并限制条数;构造器 API 使用 orderByCosine(...).initPage(10, 0)。仅调用 vectorByCosine 过滤距离,不等同于索引近邻查询。

距离定义与索引选项见 pgvector 文档

组合查询

标量条件与向量条件组合到 WHERE 中。eq(...).orderByCosine(...).initPage(k, 0) 返回满足标量条件的近邻;使用近似索引时,过滤后可能不足 k 条,不能把 k 当作保证命中条数。用法见组合条件