通过 Pigsty、Docker、Linux 软件源、Homebrew 或源码编译安装 pgvector,启用扩展并执行向量写入与批量导入。
这是本节的多页打印视图。 .
pgvector 文档
- 1: 安装与快速上手
- 2: 查询与过滤检索
- 3: HNSW 与 IVFFlat 索引
- 4: 向量量化与稀疏向量
- 5: 参考手册、调优与 FAQ
pgvector 是 PostgreSQL 生态中最基础的开源向量相似性检索扩展。它提供了核心的 vector、halfvec、bit 与 sparsevec 向量数据类型、距离操作符,以及内置的 HNSW 和 IVFFlat 索引访问方法。
vchord 的关系核心特性
- 精确与近似最近邻检索(KNN / ANN):与 PostgreSQL 完整 ACID 事务、时间点恢复(PITR)、关系连接(JOIN)及谓词过滤无缝融合。
- 多种向量数据表示:
- 单精度浮点向量(
vector,索引最高支持 2,000 维,无索引存储最高支持 16,000 维) - 半精度浮点向量(
halfvec,索引最高支持 4,000 维) - 二值位向量(
bit,索引最高支持 64,000 维) - 稀疏向量(
sparsevec,最高支持 1,000 个非零元素、总维度高达 100 万维)
- 单精度浮点向量(
- 六种距离度量:欧氏 L2 距离(
<->)、内积(<#>)、余弦距离(<=>)、曼哈顿 L1 距离(<+>)、汉明距离(<~>)以及杰卡德距离(<%>)。 - 迭代式索引扫描(Iterative Index Scans,0.8.0+):当带
WHERE过滤条件导致候选集不足时,自动扩展 HNSW 或 IVFFlat 索引遍历范围以保证召回数量。
文档章节导航
距离操作符、相似度计算、向量聚合函数、带 WHERE 条件的迭代索引扫描以及全文/BM25 混合检索。
HNSW 与 IVFFlat 索引构建与参数调优、并行建索引、进度监控,以及使用 vchord 突破内存瓶颈。
半精度(halfvec)、二值量化(bit + 精确重排)、稀疏向量(sparsevec)以及套娃(Matryoshka)子向量索引。
完整 SQL 函数与操作符速查表、GUC 参数、内存规划、执行计划排查与常见问题解答。
在现有的 pgvector 向量列上无缝添加 vchordrq 与 vchordg RaBitQ 索引,无需修改业务查询即可扩展至亿级规模。
1 - 安装与快速上手
安装方式
Pigsty / Linux 原生软件包(推荐)
Pigsty 为 Debian、Ubuntu 以及 RHEL/Rocky/AlmaLinux(x86_64 与 ARM64 架构)提供了针对 PostgreSQL 14–18 预编译的原生 pgvector(v0.8.2)软件包:
如果您同时需要磁盘友好的 RaBitQ 向量索引与原生 BM25 检索能力,可以一次性安装完整的 Vchord 套件:
Docker 容器
直接启动官方 pgvector 容器镜像:
或者使用开箱即用的 Vchord 全家桶镜像(内置 pgvector、vchord、vchord_bm25 与 pg_tokenizer):
Linux 官方软件源(PGDG APT / YUM)
- Debian / Ubuntu(通过 PostgreSQL APT 仓库):
- RHEL / Rocky / AlmaLinux / Fedora(通过 PostgreSQL YUM 仓库):
macOS(Homebrew)
从源码编译安装(Linux / macOS)
请确保系统已安装 PostgreSQL 开发头文件(postgresql-server-dev-* 或 postgresql*-devel)、make 及 C 编译器:
默认情况下,pgvector 的 Makefile 会在编译器支持时自动启用 -march=native 以最大化当前机器的 SIMD 吞吐性能。如果您需要构建跨不同代际 CPU 通用的可移植二进制包,请使用 make OPTFLAGS=""。
启用扩展
连接到目标数据库并启用 vector 扩展(需要在每个使用向量功能的数据库中执行一次):
查看当前安装的扩展版本:
升级 pgvector
在服务器上更新二进制包后,在数据库中执行以下命令升级 SQL 目录对象定义:
快速上手
1. 创建包含向量列的表
创建一个包含 3 维单精度浮点(float32)向量的表:
也可以向已有表中添加向量列:
2. 插入、更新与删除向量
使用文本字面量格式 '[x1,x2,x3]' 插入向量:
使用 ON CONFLICT 执行 Upsert(插入或更新):
使用标准 SQL 更新或删除记录:
3. 使用 COPY 批量导入
对于百万级以上的大规模数据集,强烈建议使用二进制 COPY 替代逐行 INSERT:
4. 查询最近邻向量
按欧氏距离(L2)检索距离 '[3,1,2]' 最近的 5 条记录:
接下来请阅读查询与过滤检索了解所有距离度量与过滤查询模式,或参阅HNSW 与 IVFFlat 索引了解如何加速大规模表上的近似检索。
2 - 查询与过滤检索
距离操作符
pgvector 提供六种距离操作符,可用于排序(ORDER BY)与阈值过滤:
| 操作符 | 距离度量 | 支持的数据类型 | 说明 |
|---|---|---|---|
<-> |
欧氏距离(L2) | vector, halfvec, sparsevec |
|
<#> |
负内积(Negative Inner Product) | vector, halfvec, sparsevec |
返回 (因为 PostgreSQL 索引扫描仅支持升序 ASC 排序) |
<=> |
余弦距离(Cosine Distance) | vector, halfvec, sparsevec |
(取值范围 [0, 2]) |
<+> |
曼哈顿距离(L1) | vector, halfvec, sparsevec |
(\sum |
<~> |
汉明距离(Hamming Distance) | bit |
两个位向量中不同比特位的数量(XOR 置位计数) |
<%> |
杰卡德距离(Jaccard Distance) | bit |
(1 - \frac{ |
如果您的嵌入向量已经归一化为单位长度(例如 OpenAI text-embedding-3-* 或 BGE 模型输出),建议优先使用内积(<#>)而非余弦距离(<=>),以获得更高的 CPU 计算吞吐量。
最近邻检索示例
计算距离与相似度得分
在查询结果中同时返回距离或相似度数值:
距离阈值过滤查询
检索距离在指定半径内的所有记录:
结合 ORDER BY 与 LIMIT 可直接利用 HNSW 或 IVFFlat 索引:
vchord 的原生球面范围查询如果您的业务需要频繁按距离半径做范围过滤,vchord 提供了专用的 <<->> 球面操作符(WHERE embedding <<->> sphere('[3,1,2]'::vector, 5)),可直接在 vchordrq 或 vchordg 索引内部完成半径剪枝,而无需强制携带 ORDER BY ... LIMIT。详见 vchord 相似度范围过滤。
向量聚合函数
计算一组向量的均值中心(AVG)或逐元素累加和(SUM):
条件过滤(WHERE)与迭代式索引扫描
将向量相似性检索与结构化关系谓词结合:
为过滤列建立索引
- 在过滤列上创建标准 B-tree 索引(适用于
category_id = 123选择率极高、仅匹配极少行数的场景): - 创建部分向量索引(Partial Index)(适用于仅按少数固定类别过滤的场景):
- 表分区(Partitioning)(适用于按租户或时间范围高频过滤的大表):
迭代式索引扫描(Iterative Index Scans,pgvector 0.8.0+)
默认情况下,近似向量索引扫描只会访问固定数量的候选集(hnsw.ef_search 或 ivfflat.probes)。如果 WHERE 过滤条件过滤掉了绝大部分候选行,最终返回的行数可能会少于 LIMIT。
自 pgvector 0.8.0 起,您可以开启迭代式索引扫描(Iterative Index Scans),让索引在候选结果不足时自动继续向后搜索,直到凑齐 LIMIT 条记录(或达到 max_scan_tuples / max_probes 上限):
使用 relaxed_order 时,返回结果的距离顺序可能存在轻微乱序,可通过外层 CTE 对最终的 LIMIT 条结果重排序:
控制迭代扫描开销上限
混合检索(Hybrid Search)
您可以使用 倒数排序融合(Reciprocal Rank Fusion, RRF) 将 pgvector 语义检索与关键词全文检索结合。
结合 PostgreSQL 内置 tsvector
结合 vchord_bm25 或 pg_bestmatch
如果您需要具备文档长度归一化与全局语料库 IDF 权重的标准 Okapi BM25 排序:
- 将
pgvector(或vchord)与vchord_bm25及pg_tokenizer搭配使用——详见混合检索指南。 - 或使用
pg_bestmatch在数据库内直接生成带 BM25 权重的sparsevec稀疏向量,并通过pgvector的 HNSW(sparsevec_ip_ops)索引加速检索。
3 - HNSW 与 IVFFlat 索引
默认情况下,pgvector 执行精确最近邻搜索(全表顺序扫描),具有 100% 的召回率。当表数据量增长至数万行以上时,可以通过创建近似最近邻(ANN)索引,以极小的召回率折中换取几个数量级的查询加速。
pgvector 内置了两种索引访问方法:
- HNSW(Hierarchical Navigable Small World,分层可导航小世界图):多层近邻图结构。查询速度与召回率表现显著优于 IVFFlat,且无需预先训练步骤;代价是索引构建时间更长、内存占用更高。
- IVFFlat(Inverted File with Flat Vectors,倒排文件索引):基于 K-means 聚类将向量划分到不同倒排列表。建索引速度更快、体积更小,但必须在表中已有数据的前提下创建,且相同延迟下的召回率低于 HNSW。
HNSW 索引
HNSW 索引构建了一个多层导航图。与 IVFFlat 不同,HNSW 没有聚类训练阶段,因此可以在空表上预先创建索引。
创建 HNSW 索引
根据查询语句中使用的距离操作符,选择对应的操作符类(Operator Class):
HNSW 索引支持的最大维度上限:
vector:最高 2,000 维halfvec:最高 4,000 维bit:最高 64,000 维sparsevec:最高 1,000 个非零元素
HNSW 构建参数
m(默认16,范围2–100):每个节点在每层图中的最大双向连接数。提高m可改善高内在维度数据集上的召回率,但会增加索引体积与构建耗时。ef_construction(默认64,范围4–1000):建图时的动态候选列表大小,必须满足 。
HNSW 查询参数
通过 hnsw.ef_search(默认 40,范围 1–1000)控制查询时的动态候选集大小。增大该值可提升召回率:
加速 HNSW 索引构建
当 HNSW 图结构超出 maintenance_work_mem 容量时,建索引速度会急剧下降。在大表上创建 HNSW 索引前,请调大 maintenance_work_mem 与并行维护工作进程数:
建议始终在完成 COPY 初始数据批量导入之后再创建 HNSW 索引。在生产环境中,请使用 CREATE INDEX CONCURRENTLY 以避免阻塞在线写入。
IVFFlat 索引
IVFFlat 索引利用 K-means 聚类将向量空间划分为 lists 个倒排分桶,查询时仅扫描距离查询向量最近的 ivfflat.probes 个分桶。
由于 IVFFlat 在 CREATE INDEX 期间计算 K-means 聚类中心,您必须在表中已有代表性数据之后再创建该索引。
创建 IVFFlat 索引
根据表的总行数设置 lists 参数:
- 100 万行以内:
rows / 1000 - 超过 100 万行:
sqrt(rows)
IVFFlat 索引支持的最大维度上限:
vector:最高 2,000 维halfvec:最高 4,000 维bit:最高 64,000 维
IVFFlat 查询参数
通过 ivfflat.probes(默认 1)设置每次查询探测的倒排列表数量,推荐初始值为 sqrt(lists):
索引构建进度监控与维护
监控建索引进度
在 CREATE INDEX 执行期间查询 pg_stat_progress_create_index:
- HNSW 阶段:
initializingloading tuples - IVFFlat 阶段:
initializingperforming k-meansassigning tuplesloading tuples
HNSW 索引的 VACUUM 维护
在大批量删除数据后,直接对 HNSW 索引执行 VACUUM 可能会因为修复图边连接而耗时较长。此时可先并发重建索引,再执行 VACUUM:
4 - 向量量化与稀疏向量
pgvector 支持四种向量数据类型,方便您在内存占用、维度上限与检索召回率之间灵活权衡:
| 数据类型 | 元素精度 | 索引最大维度上限 | 存储空间占用 |
|---|---|---|---|
vector(n) |
32 位浮点(float32) |
2,000 维 | 字节 |
halfvec(n) |
16 位半精度浮点(float16) |
4,000 维 | 字节 |
bit(n) |
1 位二值比特(0 / 1) |
64,000 维 | 字节 |
sparsevec(n) |
非零 下标:float32 键值对 |
最多 1,000 个非零元素(总维度可达 100 万) | 字节 |
vchord 中的 RaBitQ 量化除了 pgvector 内置的量化类型外,vchord 还提供 rabitq8(8-bit)与 rabitq4(4-bit)专用量化向量类型,并在 vchordrq 索引中支持高达 60,000 维的超长向量。详见 vchord 量化类型。
半精度浮点向量(halfvec)
使用 halfvec 类型(自 pgvector 0.7.0 起引入)存储 16 位半精度浮点向量,相比 vector 可将表与索引体积直接缩减 50%:
半精度表达式索引(标量量化)
如果您希望在表中保留完整的 32 位 vector 精度(或者需要为 2,001 至 4,000 维的向量建索引,例如 3,072 维的 OpenAI text-embedding-3-large),可以通过表达式索引将 vector 转换为 halfvec:
二值向量(bit)与二值量化
结合 PostgreSQL 内置的 bit(n) 类型与 pgvector 的汉明距离(<~>)及杰卡德距离(<%>)操作符,可存储并索引高达 64,000 位的二值向量:
二值量化索引 + 全精度重排序(Re-Ranking)
使用 binary_quantize(vector) 函数在表达式索引中将每个维度压缩为 1 比特(大于 0 为 1,否则为 0),并在子查询召回候选集后使用原始 vector 列执行精确重排:
稀疏向量(sparsevec)
使用 sparsevec(自 pgvector 0.7.0 起引入)存储绝大部分维度为零的稀疏向量(例如 SPLADE、BGE-M3 稀疏输出,或由 pg_bestmatch 生成的 BM25 词频权重向量)。
稀疏向量字面量格式
语法格式为 '{下标1:值1,下标2:值2}/总维度',其中下标从 1 开始计数:
套娃(Matryoshka)子向量索引(subvector)
对于支持套娃表示学习(Matryoshka Representation Learning, MRL)的嵌入模型,可以使用 subvector(vector, start, count) 仅对前 个维度建立轻量级索引,再利用完整向量执行精确重排:
5 - 参考手册、调优与 FAQ
SQL 函数与操作符速查表
向量函数
| 函数 | 返回类型 | 说明 |
|---|---|---|
l2_distance(a, b) |
float8 |
计算 a 与 b 之间的欧氏(L2)距离(支持 vector, halfvec, sparsevec) |
inner_product(a, b) |
float8 |
计算内积 (支持 vector, halfvec, sparsevec) |
cosine_distance(a, b) |
float8 |
计算余弦距离 (支持 vector, halfvec, sparsevec) |
l1_distance(a, b) |
float8 |
计算曼哈顿(L1)距离 (\sum |
hamming_distance(a, b) |
float8 |
计算两个 bit 位向量之间的汉明距离 |
jaccard_distance(a, b) |
float8 |
计算两个 bit 位向量之间的杰卡德距离 |
vector_dims(a) |
integer |
返回向量的维度数(支持 vector, halfvec, sparsevec) |
vector_norm(a) |
float8 |
返回向量的欧氏范数 (支持 vector, halfvec, sparsevec) |
l2_normalize(a) |
与输入相同 | 将向量归一化为单位 L2 长度(支持 vector, halfvec, sparsevec) |
binary_quantize(a) |
bit |
将 vector 或 halfvec 的每个元素二值化为 1()或 0() |
subvector(a, start, count) |
与输入相同 | 从 1 起始下标 start 处截取长度为 count 的子向量(支持 vector, halfvec) |
逐元素算术操作符
a + b:逐元素加法(vector,halfvec)a - b:逐元素减法(vector,halfvec)a * b:逐元素乘法(vector,halfvec)a || b:向量拼接(vector,halfvec)
GUC 配置参数
| 参数名称 | 类型 / 允许取值 | 默认值 | 说明 |
|---|---|---|---|
hnsw.ef_search |
integer(1–1000) |
40 |
HNSW 查询时的动态候选列表大小 |
hnsw.iterative_scan |
off, relaxed_order, strict_order |
off |
当 WHERE 条件过滤导致结果少于 LIMIT 时,自动继续扫描 HNSW 索引 |
hnsw.max_scan_tuples |
integer |
20000 |
HNSW 迭代扫描期间最多访问的元组数量 |
hnsw.scan_mem_multiplier |
real |
1 |
HNSW 迭代扫描维护访问状态可使用的 work_mem 倍数 |
ivfflat.probes |
integer(1–lists) |
1 |
IVFFlat 查询时探测的倒排列表数量 |
ivfflat.iterative_scan |
off, relaxed_order |
off |
当 WHERE 条件过滤导致结果少于 LIMIT 时,自动探测更多 IVFFlat 分桶 |
ivfflat.max_probes |
integer |
32768 |
IVFFlat 迭代扫描期间最多探测的倒排列表数量 |
性能调优与监控
1. 查看索引体积
2. 检查查询执行计划
使用 EXPLAIN ANALYZE 确认查询是否命中向量索引并查看缓冲区命中与耗时:
3. 使用 pg_stat_statements 监控慢查询
4. 评估近似检索召回率(Recall)
在事务内临时关闭索引扫描,获取精确最近邻基准(Ground Truth)并与近似结果对比:
常见问题解答(FAQ)
为什么我的查询没有走向量索引?
- 缺少
ORDER BY ... LIMIT:向量索引扫描要求查询同时包含ORDER BY <距离操作符>与LIMIT子句。 - 操作符与索引操作符类不匹配:查询操作符必须与创建索引时的操作符类一致(
<->对应vector_l2_ops,<#>对应vector_ip_ops,<=>对应vector_cosine_ops)。 - 小表成本估算:当表行数较少时,PostgreSQL 优化器认为全表顺序扫描比走索引更快。在测试环境中可通过
SET LOCAL enable_seqscan = off;强制走索引验证。
如何对超过 2,000 维的向量建立索引?
受限于 PostgreSQL 8 KB 页面元组大小,内置的 HNSW 与 IVFFlat 索引对 vector 类型的维度上限为 2,000 维。您有三种解决方案:
- 安装
vchord:vchord的vchordrq索引直接在vector与halfvec列上支持高达 60,000 维的超长向量。 - 使用
halfvec半精度表达式索引:通过(embedding::halfvec(3072)) halfvec_l2_ops最高支持 4,000 维。 - 使用二值量化表达式索引:通过
(binary_quantize(embedding)::bit(N)) bit_hamming_ops最高支持 64,000 维。
可以在同一列中存储不同维度的向量吗?
可以,定义列时不指定维度即可(embedding vector)。如果需要建索引,可以针对特定维度的行创建部分表达式索引:
向量中可以包含 NULL、NaN 或 Infinity 吗?
向量内部的元素不能为 NULL、NaN 或 Infinity。整列的值可以为 NULL;请注意 IVFFlat 不会对 NULL 值建索引。