pgvector 向量数据库手册
pgvector 向量数据库手册
适用版本:pgvector 0.8.7 稳定版(0.8.6 同期在维护;0.9.0 为 unreleased,勿用于生产),核实于 2026-11 许可与形态:PostgreSQL License(官方 LICENSE 正文未直接核验,以官方仓库为准);PostgreSQL 扩展(依附已有 PG 实例,无独立进程 / 端口 / 存储) 一句话定位:给已有 PostgreSQL 装一个
vector扩展,用同一条 SQL 同时完成关系查询与向量近邻检索,不新增一套数据库。 约定:$普通用户、#root 或 sudo、<xxx>为占位符;标 ⚠️ 的是高危操作。 更新时间:2026-11(版本与 API 变化快,执行前请以官方文档复核)
目录
1. 它是什么、什么时候选它
1.1 定位与架构
pgvector 不是独立服务,而是 PostgreSQL 的扩展(extension):向 PG 注入向量类型(vector / halfvec / bit / sparsevec)、距离运算符(<-> 等)、索引访问方法(hnsw / ivfflat)。分层如下。
| 分层 | 形态 | 运维含义 |
|---|---|---|
| 进程层 | 检索在 PG 后端进程(backend)内执行 | 复用连接、事务、锁、优化器,无额外进程 |
| 存储层 | 向量列存堆表(heap),索引是 PG 索引关系 | 都写 WAL,受 MVCC / 流复制 / PITR 管辖 |
| 接口层 | 仅 SQL,走 PostgreSQL 协议 | 复用现有 PG 驱动,无独立 REST / gRPC 端口 |
| 部署层 | vector.so + 扩展 SQL 加载进 PG |
升级 = 换包 + ALTER EXTENSION |
本册核心主题是「不新增一套数据库」:已有 PG 时,向量能力只是加一个扩展,而不是再部署一套 Milvus / Qdrant 集群。
| 维度 | pgvector(融合型) | 专用向量库(Milvus / Qdrant) | 索引库(Faiss / hnswlib) |
|---|---|---|---|
| 独立服务 | 否,PG 扩展 | 是,独立集群 | 否,进程内库 |
| 数据主权 | 与业务表同库、同事务 | 独立系统 | 应用自管 |
| 标量 + 向量混合 | 原生 SQL WHERE + ORDER BY |
各自 filter DSL | 自行实现 |
| 事务 / MVCC / JOIN | 完整继承 PG | 通常弱或无 | 无 |
| 分布式 | 依赖 PG 方案 | 原生分片副本 | 无 |
| 性能上限 | 受单机 PG 约束 | 面向十亿级高并发 | 受单机内存约束 |
适合:① 业务数据本就在 PG,向量只是给已有表加一列;② 需「本租户 / 近 7 天 / 状态有效」这类标量 + 向量强一致 TopK;③ 业务记录与向量需同事务原子提交;④ 规模中等且已有成熟 PG 备份 / 监控 / 高可用;⑤ RAG 中小规模生产,追求最短链路。
不适合:① 千万~亿级且高 QPS;② 需 GPU、弹性多副本、按向量分片;③ 需内核级多向量 / 稀疏 / 复杂重排;④ 维度超 vector 可索引上限(2000)还要 ANN;⑤ 托管 PG 不允许装扩展或不能升到 0.8.4+。
1.2 规模、链路位置与「何时该换」
| 项 | 经验区间(非官方承诺,须实测) |
|---|---|
| < 10 万条 | 精确扫描 ORDER BY <-> ... LIMIT k 通常够用,可不建 ANN |
| 10 万 ~ 数百万 | HNSW / IVFFlat + 迭代扫描,调 ef_search / probes |
| 千万以上 / 高 QPS | 评估专用向量库或分片,PG 单机受内存 / WAL 制约 |
| 维度 | 常见 768 / 1024 / 1536;vector 可索引 ≤2000、存储 ≤16000 |
| QPS | 经验上几十~几百量级,强依赖 CPU 与 ef_search |
链路位置:离线「文档/图片 → Embedding 服务 → 写入 items.embedding(与业务行同库)」;在线「query → Embedding → SELECT ... WHERE <业务条件> ORDER BY embedding <-> $q LIMIT k → 回表取原文 → 重排 → LLM / 展示」。pgvector 只负责带业务条件的召回层。
该换专用向量库的信号(满足两条以上):规模 / QPS 增长到 PG 单机扛不住;过滤命中率低导致迭代扫描也难保召回;需十亿级分布式或 GPU;向量检索成核心链路要独立隔离;需内核级 BM25 + 稠密 + RRF 融合而不想在应用层自己拼。
2. 版本、许可与官方入口
2.1 版本状态表
| 版本线 | 时间 | 状态 | 备注 |
|---|---|---|---|
| 0.8.7 | 2026-10-01 | 稳定 / 推荐 | 生产目标;修复 IVFFlat 建索引缓冲区溢出 |
| 0.8.6 | 2026-07-29 | 稳定 | 同为 IVFFlat 缓冲区溢出修复线 |
| 0.8.4 | 日期未核实 | 生产 HNSW 最低要求 | 修复 hnsw graph not repaired |
| 0.8.3 | 日期未核实 | 历史 | 修复 HNSW vacuum 索引损坏 |
| 0.8.1 | 日期未核实 | 历史 | 增加 PostgreSQL 18 支持 |
| 0.8.0 | 日期未核实 | 历史 | 引入 hnsw.iterative_scan / ivfflat.iterative_scan |
| 0.9.0 | 日期未核实 | unreleased(master) | 已写明 Dropped support for Postgres 13 and 14 |
避坑:网上「pgvector 0.9.0 教程」指向 master 未发布分支。选型与发版公告的稳定版一律写 0.8.7。 版本差异:0.9.0 已丢 PG13 / PG14;若 PG 是 13 / 14,连升级路径都要重新核对。
2.2 许可、入口与版本识别
- 许可:PostgreSQL License(官方 LICENSE 正文未直接核验,以官方仓库为准)。无「社区版 / 企业版」能力分叉,商业支持来自 PG 发行方或云厂商。
- PG 兼容:README 标 Postgres 13+,0.8.1 增加 PG18 支持;0.9.0 起不再支持 PG13 / PG14。云托管是否允许
CREATE EXTENSION由厂商白名单决定(经验性,非 pgvector 限制)。 - 官方入口:仅 https://github.com/pgvector/pgvector (含 README / CHANGELOG / LICENSE)核实;官网、独立文档站、镜像仓库、SDK、控制台 URL 官方资料未提供,勿臆测。
SELECT extversion FROM pg_extension WHERE extname = 'vector'; -- 扩展版本
SELECT version(); -- PG 服务端版本
$ psql -d <dbname> -c "\dx vector" # PG 通用元命令
2.3 近两年重要变更与弃用提醒
| 变更 | 影响 |
|---|---|
| 0.8.0 引入迭代扫描 | 解决「ANN + WHERE」召回不足,本篇最重要参数 |
| 0.8.1 支持 PG18 | 升 PG18 需 ≥0.8.1 |
| 0.8.3 修 HNSW vacuum 索引损坏 | 更早版本有数据损坏风险 |
0.8.4 修 hnsw graph not repaired |
生产 HNSW 最低 ≥0.8.4 的依据 |
| 0.8.6 / 0.8.7 修 IVFFlat 建索引缓冲区溢出 | 用 IVFFlat 建议直接 0.8.7 |
| 0.9.0(unreleased)丢 PG13 / PG14 | 仅影响 master,勿当稳定版 |
避坑:
ALTER EXTENSION vector UPDATE只更新扩展对象定义,不会重建已存在的 HNSW 图;从 0.8.3 及更早升级后应REINDEX。
3. 安装与启动
3.1 前置条件与两种方式
依赖:PostgreSQL 13+(0.8.1 起支持 PG18);C 编译器与 PG 服务端开发头文件(通用编译依赖,包名随发行版而异);具备 CREATE EXTENSION 权限的角色。换 PG 大版本后需重新编译安装。
方式一:源码编译(Linux / macOS)
$ git clone --branch v0.8.7 https://github.com/pgvector/pgvector.git
$ cd pgvector
$ make
# make install
CREATE EXTENSION vector; -- 每个数据库各执行一次
避坑:扩展名是
vector,不是pgvector;CREATE EXTENSION pgvector;会报 extension 不可用。
方式二:Windows(nmake):nmake /F Makefile.win。编译产物的安装部署步骤官方资料未提供逐字命令,按仓库 Windows 说明执行,勿臆测参数。
其他渠道:官方资料确认支持 Docker / PGXN / APT / yum / conda-forge,但未给逐字命令与镜像 tag,按各渠道官方文档执行,不要凭印象写镜像名或 tag。
| 目录 / 端口 | 说明 |
|---|---|
| 端口 5432 | PG 通用默认;pgvector 无独立端口,以实际 postgresql.conf 为准 |
| 扩展 SQL | $(pg_config --sharedir)/extension/vector*.sql |
共享库 vector.so |
$(pg_config --pkglibdir)/ |
| 数据 / 索引 | 均在 PGDATA,纳入现有 PG 备份 |
| 日志 | PG log_directory;无独立日志 |
3.2 健康检查、生产最小配置
SELECT extversion FROM pg_extension WHERE extname = 'vector'; -- 返回版本号即就绪
SELECT '[1,2,3]'::vector <-> '[3,1,2]'::vector AS l2_distance; -- 返回数值即运算符可用
示例用 3 维,实际常见 768 / 1024 / 1536。认证 / TLS / 网络沿用 PG 角色体系与 pg_hba.conf;通用 Linux 运维(systemctl / 防火墙基础)见根目录手册,此处不重复。持久化无需单独挂盘;建索引前评估 maintenance_work_mem,查询侧按 ef_search 评估 work_mem(经验值,实测为准)。
⚠️ 危险:大表直接
CREATE INDEX USING hnsw会长时间持锁并占资源,务必在维护窗口、有备份、已评估内存的前提下执行。
4. 核心概念与数据模型
4.1 术语、类型与距离
| pgvector 术语 | 通用术语 | 关系型类比 |
|---|---|---|
extension (vector) |
扩展 | CREATE EXTENSION |
vector(n) |
稠密向量列 | 定长类型列 |
<-> / <=> 等 |
距离运算符 | 表达式 |
hnsw / ivfflat |
ANN 索引 | CREATE INDEX ... USING |
ORDER BY embedding <-> $q LIMIT k |
TopK 近邻 | 排序 + LIMIT |
opclass(如 vector_l2_ops) |
运算符类 | 索引绑定的距离语义 |
数据模型:database → schema → table(标量列 + 一个/多个向量列)→ index。一行 = 一个实体(id + 业务标量 + embedding),没有 collection / partition / segment 概念,也没有「load 集合才能检索」这一步;跨实体隔离靠 schema 或标量列。
| 类型 | 元素 | 维度上限(官方资料口径) | 说明 |
|---|---|---|---|
vector |
float4 | 可索引 ≤2000,存储 ≤16000 | 默认稠密类型 |
halfvec |
半精度 | ≤4000 | 半精度压缩 |
bit |
位 | ≤64000 | 二值,配合 Hamming / Jaccard |
sparsevec |
稀疏 float4 | 未核实 | IVFFlat 不支持 sparsevec |
| 运算符 | 度量 | 数值方向 | ORDER BY |
|---|---|---|---|
<-> |
L2 欧氏 | 越小越相似 | ASC |
<#> |
负内积 | 越小越相似(等价内积越大) | ASC |
<=> |
余弦距离 | 越小越相似 | ASC |
<+> |
L1 曼哈顿 | 越小越相似 | ASC |
<~> |
Hamming | 越小越相似 | ASC |
<%> |
Jaccard | 越小越相似 | ASC |
避坑:
<#>返回的是负内积,ORDER BY embedding <#> $q取最小即「内积最大」,别按「内积越大越相似」写 DESC。 索引必须绑定与查询一致的 opclass(官方示例为vector_l2_ops);ORDER BY表达式与建索引 opclass 不匹配会让索引失效退化为全表扫描。其他距离的 opclass 名称未查到官方明确说明,以官方文档为准。
4.2 索引参数、生命周期与一致性
| 索引 | 参数 | 默认值 | 作用 |
|---|---|---|---|
| HNSW | m |
16 | 每层连接数,越大召回越好、索引越大 |
| HNSW | ef_construction |
64 | 建索引候选集,越大图质量越好 |
| HNSW | hnsw.ef_search |
40 | 查询候选集(会话 GUC),主调优旋钮 |
| HNSW | hnsw.iterative_scan |
0.8.0 起 | 过滤场景持续扫描凑够 LIMIT k |
| HNSW | hnsw.max_scan_tuples |
20000 | 迭代扫描元组上限 |
| HNSW | hnsw.scan_mem_multiplier |
1 | 迭代扫描内存倍数 |
| IVFFlat | lists |
未核实 | 倒排桶数 |
| IVFFlat | ivfflat.probes |
1 | 查询探测桶数 |
| IVFFlat | ivfflat.iterative_scan |
0.8.0 起 | 过滤场景继续探测 |
| IVFFlat | ivfflat.max_probes |
未核实 | 迭代扫描探测上限 |
避坑:
CREATE INDEX ... WITH (m = ..., ef_construction = ...)的参数会固化在索引里,事后改 GUC 不改变已建索引结构,要改必须REINDEX(或 DROP 后重建)。iterative_scan的取值枚举与默认值未查到官方明确说明,以官方文档为准;本篇只强调「过滤场景必须开启」。
生命周期:INSERT / UPDATE 同步写 heap + WAL 且立即可被精确扫描查到;CREATE INDEX 同步构建并持锁;后续写入索引随事务增量维护;查询由优化器决定是否走索引,全程无异步、无需 load / flush。一致性完整继承 PG 的 MVCC 与事务隔离级别,向量与业务字段可同事务原子提交。
5. 快速上手:完整 CRUD 示例
示例统一用 3 维向量便于阅读;实际常见 768 / 1024 / 1536 维。
5.1 完整 SQL 脚本(psql,可直接复制运行)
-- 连接:psql -h <host> -p <port> -U <user> -d <dbname>
CREATE EXTENSION IF NOT EXISTS vector;
DROP TABLE IF EXISTS items;
CREATE TABLE items (
id bigserial PRIMARY KEY,
content text,
category text,
embedding vector(3)
);
INSERT INTO items (content, category, embedding) VALUES
('向量检索入门', 'tech', '[1,2,3]'),
('关系型数据库运维', 'tech', '[4,5,6]'),
('咖啡拉花教程', 'life', '[7,1,2]'),
('HNSW 索引原理', 'tech', '[2,3,3]');
-- 1) 精确检索(L2,distance 越小越相似)
SELECT id, content, embedding <-> '[3,1,2]' AS distance
FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 3;
-- 2) 带标量过滤的精确检索:无 ANN 索引时 WHERE 先过滤再排序,结果完整
SELECT id, content, category, embedding <-> '[3,1,2]' AS distance
FROM items WHERE category = 'tech'
ORDER BY embedding <-> '[3,1,2]' LIMIT 3;
-- 3) 建 HNSW 索引(opclass 与查询一致,均为 L2)
CREATE INDEX ON items USING hnsw (embedding vector_l2_ops);
-- 4) ANN 检索(不带过滤)
SET hnsw.ef_search = 100;
SELECT id, content, embedding <-> '[3,1,2]' AS distance
FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 3;
-- 5) 过滤 + ANN:⚠️ 此时 WHERE 是「扫描后过滤」,可能返回少于 3 条
-- 必须开迭代扫描:SET hnsw.iterative_scan = <取值,见官方文档>;
SELECT id, content, category, embedding <-> '[3,1,2]' AS distance
FROM items WHERE category = 'tech'
ORDER BY embedding <-> '[3,1,2]' LIMIT 3;
-- 6) 更新 7) 删除 8) 清理
UPDATE items SET embedding = '[1,2,4]' WHERE id = 1;
DELETE FROM items WHERE id = 3;
DROP TABLE items;
-- DROP EXTENSION vector; -- 仅在确认无依赖对象时执行
避坑:第 5 步是全篇最重要的坑。旧教程把
WHERE与ORDER BY ... LIMIT k直接组合,默认「先过滤再找近邻」。pgvector 的 ANN 索引恰恰相反:索引按距离吐出候选后再套WHERE,过滤命中率低时结果变少甚至为空。0.8.0 起必须开hnsw.iterative_scan(IVFFlat 用ivfflat.iterative_scan)。
5.2 输出怎么读与 Python 等价示例
| 列 | 含义 |
|---|---|
id |
业务主键,用于回表取原文 / 图片 |
content / category |
标量列,验证同库 JOIN 与过滤生效 |
distance |
L2 距离,越小越相似,不是相似度分数 |
若第 5 步行数不足或 distance 反而变大,说明迭代扫描没开、候选被提前截断。
import psycopg
PG_HOST = "127.0.0.1"
PG_PORT = 5432 # PG 通用默认端口,按实际配置修改
PG_DB = "vectordemo"
PG_USER = "app"
PG_PASSWORD = "<password>"
QUERY_VEC = "[3,1,2]" # 示例 3 维,实际常见 768 / 1024 / 1536
conn = psycopg.connect(host=PG_HOST, port=PG_PORT, dbname=PG_DB,
user=PG_USER, password=PG_PASSWORD)
cur = conn.cursor()
cur.execute("CREATE EXTENSION IF NOT EXISTS vector")
cur.execute("CREATE TABLE IF NOT EXISTS items (id bigserial PRIMARY KEY, "
"content text, category text, embedding vector(3))")
cur.execute("INSERT INTO items (content, category, embedding) VALUES (%s, %s, %s)",
("向量检索入门", "tech", "[1,2,3]"))
cur.execute("SELECT id, content, embedding <-> %s AS distance FROM items "
"ORDER BY embedding <-> %s LIMIT 3", (QUERY_VEC, QUERY_VEC))
for row in cur.fetchall():
print(row)
conn.commit()
cur.close()
conn.close()
避坑:旧教程会写成
CREATE EXTENSION pgvector;(扩展名错)以及字符串拼接$q(注入风险);当前写法是CREATE EXTENSION vector+ 参数化%s。psycopg属通用第三方驱动,方法名以所用驱动版本文档为准;REST / cURL 等价示例不适用——pgvector 无独立 HTTP 接口,全部经 PostgreSQL 协议访问。
6. 索引与检索进阶
6.1 参数调优、过滤行为
| 参数 | 默认值 | 影响 | 建议范围(经验值,实测为准) |
|---|---|---|---|
m |
16 | 连接数↑ → 召回↑、体积↑、构建慢 | 16 起步,高维可上调 |
ef_construction |
64 | 建索引候选↑ → 图质量↑ | 64~200,一次性成本 |
hnsw.ef_search |
40 | 查询候选↑ → 召回↑、延迟↑ | 40~200 逐步压测 |
hnsw.max_scan_tuples |
20000 | 迭代扫描上限 | 按过滤命中率调 |
lists(IVFFlat) |
未核实 | 桶数↑ → 需更大 probes | 按数据量经验取值 |
ivfflat.probes |
1 | 探测桶↑ → 召回↑、延迟↑ | 从小值逐步加 |
recall 与延迟:ef_search / probes 是最直接的旋钮,调大 → 召回提高、P99 延迟上升。调参方法(经验):先无索引精确扫描跑 ground truth,再对同一批 query 算 recall@k,逐步加大候选数直到达标。
| 场景 | 过滤时机 | 结果完整性 | 处置 |
|---|---|---|---|
| 无 ANN 索引,精确扫描 | pre-filter(先 WHERE 再排序) | 完整精确 | 小数据量首选 |
| HNSW / IVFFlat 索引 | 扫描后过滤(post-filter 语义) | 可能少于 LIMIT k 甚至为空 |
开迭代扫描 |
开 hnsw.iterative_scan |
持续吐候选直到凑够 k | 召回显著改善 | 配 max_scan_tuples 兜底 |
6.2 混合检索、多向量与容量估算
- 混合检索:pgvector 不内置 RRF 融合函数(官方资料未提供相关函数名,勿臆测)。经验做法是 PG 原生全文检索(
tsvector/tsquery,属 PG 能力)与<->各取 TopK,在应用层按 RRF 或加权分数融合。若混合检索成核心且需内核级优化,即第 1.2 节「该换专用向量库」的信号。 - 多向量 / 稀疏 / 重排:一表多个
vector列或「一行一向量」多行聚合;sparsevec不支持 IVFFlat;常见两阶段结构是 ANN 取大候选 + 精确距离 / 业务权重重排。 - 量化压缩:
halfvec约省一半存储、精度略降;bit配<~>/<%>压缩比极高但只适合二值 embedding;sparsevec省高维稀疏空间但索引类型受限。
单行向量存储 ≈ 8 字节(类型头) + 4 × dim 字节(vector 为 float4)
dim = 768 → 8 + 3072 = 3080 B ≈ 3.0 KB / 行;100 万行 ≈ 3.08 GB(仅向量列)
HNSW 索引体积 ≈ 原始向量体积 × (1.2 ~ 2) + 图连接开销(m 越大越占内存)
建索引临时空间 ≈ 与 maintenance_work_mem 相关,不足会落盘并显著变慢
以上为经验公式,非官方承诺;请用
pg_relation_size实测后做容量规划。
7. 生产部署与运维
- 高可用:向量列与索引随 WAL 复制,PG 流复制备库可承担只读向量查询;无内置按向量分片,水平拆分靠 PG 分区表 / 应用层路由 / 分布式扩展(经验性)。注意 HNSW 增量维护的 WAL 放大。
- 备份恢复:逻辑备份(
pg_dump/pg_restore)恢复时按 DDL 重建索引,无需单独手工重建;物理备份(pg_basebackup/ PITR)索引文件随数据恢复;跨 PG 大版本升级建议REINDEX校验。 - 监控(无独立端点,复用 PG
pg_stat_*与现有采集):
| 指标 | 关注点 | 告警阈值(经验值) |
|---|---|---|
| 向量查询 P99 延迟 | ef_search 是否过大 |
相对基线翻倍即排查 |
seq_scan 大表 |
是否退化全表扫描 | 突增即告警 |
索引大小 pg_relation_size |
HNSW 增长 / 膨胀 | 超容量水位 |
| WAL 生成量 | 批量写向量后的复制压力 | 备库延迟上升即关注 |
| 连接数 / 慢查询 | 与向量查询叠加 | 沿用主库基线 |
- 扩缩容:以 6.2 估算为起点,预留索引 + WAL + 备份空间;以垂直扩容为主,大表建索引需维护窗口。
- 升级迁移:
ALTER EXTENSION vector UPDATE;(PG 通用语法,可用性以所用版本为准);路径为核对extversion→ 读 CHANGELOG → 目标 0.8.7 → 对旧 HNSW 做REINDEX。⚠️ 危险:从 <0.8.4 升级后不重建索引,可能把损坏的 HNSW 图结构继续带进生产。
- 安全 / 日志:最小权限角色、TLS、网络不暴露、扩展安装权限收敛,沿用 PG 基线;通用系统运维见根目录手册。日志由 PG
log_directory决定,pgvector 无独立日志文件。
8. 高频故障与排障
| 症状 | 可能原因 | 定位命令 | 处置 |
|---|---|---|---|
could not open extension control file |
产物未装到 extension 目录 / PG 大版本不匹配 | SELECT * FROM pg_available_extensions WHERE name='vector'; |
重装并确认 PG 版本对应 |
CREATE EXTENSION 报不存在 |
写成了扩展名 pgvector |
SELECT extname FROM pg_extension; |
改 CREATE EXTENSION vector; |
| 写入失败:维度不匹配 | 字面量维度与 vector(3) 不符 |
检查 INSERT 向量字面量 | 对齐列维度定义 |
| 查不到 / 召回低(带 WHERE 结果少于 LIMIT) | ANN 扫描后过滤,候选被截断 | EXPLAIN 看是否 Index Scan ... hnsw |
开 hnsw.iterative_scan |
| 查询慢 | 无索引 / ORDER BY 与 opclass 不一致 |
EXPLAIN ANALYZE |
建匹配 opclass 的 HNSW,调 ef_search |
| OOM / 建索引失败 | maintenance_work_mem 不足 |
查 PG 日志建索引报错 | 调大内存、错峰、维护窗口重建 |
| 磁盘满 | HNSW 索引 + TOAST + WAL 叠加 | pg_relation_size('items') |
halfvec / 降维 / 清理历史数据 |
| 索引不生效(Seq Scan) | 表太小或距离运算符与索引不匹配 | EXPLAIN SELECT ... ORDER BY ... LIMIT k; |
用与索引一致的 ORDER BY 表达式 |
升级后 hnsw graph not repaired |
旧版 HNSW 已知缺陷 | SELECT extversion FROM pg_extension WHERE extname='vector'; |
升 ≥0.8.4(目标 0.8.7)并 REINDEX |
| 过滤结果变少 / 为空 | post-filter 语义,命中率低 | EXPLAIN + 对比无索引精确结果 |
开迭代扫描或改走精确扫描 |
改 m / ef_construction 没效果 |
建索引参数固化 | SELECT pg_get_indexdef(indexrelid) FROM pg_index ...; |
REINDEX 或删掉重建 |
9. 常见坑与避坑清单
- 现象:文档写「pgvector 0.9.0」。原因:0.9.0 是 master 的 unreleased 分支。怎么做:稳定版写 0.8.7,并注明已丢 PG13/14。
- 现象:
CREATE EXTENSION pgvector;报错。原因:扩展名是vector。怎么做:一律用CREATE EXTENSION vector;。 - 现象:生产用 0.8.3 或更早 HNSW,索引损坏 /
graph not repaired。原因:0.8.3 修 vacuum 损坏、0.8.4 修 graph not repaired。怎么做:生产 HNSW 最低 ≥0.8.4,目标 0.8.7,升级后 REINDEX。 - 现象:ANN 查询带
WHERE后结果变少。原因:ANN 下 WHERE 是扫描后过滤。怎么做:开hnsw.iterative_scan(IVFFlat 用ivfflat.iterative_scan),配max_scan_tuples/max_probes。 - 现象:改了索引参数没变化。原因:
CREATE INDEX参数固化。怎么做:REINDEX或删掉重建,不要只改 GUC。 - 现象:
<#>排序方向反了。原因:它是负内积,越小越相似。怎么做:ORDER BY ... <#> $q用 ASC。 - 现象:超高维还想建
vector的 HNSW 失败。原因:vector可索引 ≤2000 维、存储 ≤16000 维。怎么做:确认维度口径,必要时用halfvec或换方案。 - 现象:IVFFlat 建在空表 / 极少数据上召回很差。原因:
lists/probes依赖数据分布(经验)。怎么做:先灌数据再建索引,调ivfflat.probes。 - 现象:对
sparsevec建 IVFFlat 失败。原因:IVFFlat 不支持 sparsevec。怎么做:改 HNSW 或精确扫描。 - 现象:
halfvec/bit建索引后查询不走索引。原因:类型与距离运算符 / opclass 不匹配。怎么做:建索引与ORDER BY用同一距离语义。 - 现象:大表
CREATE INDEX USING hnsw拖慢主库。原因:同步构建、持锁、耗内存。怎么做:⚠️ 维护窗口 + 备份 + 资源评估,可能导致线上事故。 - 现象:
SELECT *拉回大向量列导致应用内存飙升。原因:把 embedding 当普通列返回。怎么做:只 SELECT 标量列与distance,向量按需回表取。
⚠️ 危险:
DROP EXTENSION vector;会连带删除依赖该类型的列 / 索引 / 表对象,属数据丢失级操作,执行前必须确认依赖并备份。
10. 速查表
| 操作 | 命令 / 代码 | 说明 |
|---|---|---|
| 启用扩展 | CREATE EXTENSION vector; |
扩展名是 vector |
| 查扩展版本 | SELECT extversion FROM pg_extension WHERE extname='vector'; |
确认是否 ≥0.8.4 |
| 查 PG 版本 | SELECT version(); |
PG13+ |
| 建表 | CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3)); |
示例 3 维 |
| 插入 | INSERT INTO items (embedding) VALUES ('[1,2,3]'), ('[4,5,6]'); |
字面量字符串 |
| L2 检索 | SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5; |
越小越相似 |
| 余弦检索 | SELECT * FROM items ORDER BY embedding <=> '[3,1,2]' LIMIT 5; |
余弦距离 |
| 负内积检索 | SELECT * FROM items ORDER BY embedding <#> '[3,1,2]' LIMIT 5; |
负内积,ASC |
| 带过滤检索 | ... WHERE category='tech' ORDER BY embedding <-> '[...]' LIMIT 5; |
需迭代扫描 |
| 建 HNSW 索引 | CREATE INDEX ON items USING hnsw (embedding vector_l2_ops); |
官方 README 写法 |
| 建 IVFFlat 索引 | CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 100); |
lists 按数据量定 |
| 调查询候选 | SET hnsw.ef_search = 100; |
召回 / 延迟旋钮 |
| 调 IVFFlat 探测 | SET ivfflat.probes = 10; |
默认 1 |
| 开迭代扫描 | SET hnsw.iterative_scan = <取值,见官方文档>; |
过滤场景必开 |
| 迭代扫描上限 | SET hnsw.max_scan_tuples = 20000; |
默认 20000 |
| 看执行计划 | EXPLAIN ANALYZE SELECT ...; |
确认是否走索引 |
| 重建索引 | REINDEX INDEX <index_name>; |
改参数 / 升级后 |
| 升级扩展 | ALTER EXTENSION vector UPDATE; |
PG 通用语法 |
| 查索引定义 | SELECT pg_get_indexdef(indexrelid) FROM pg_index WHERE indrelid='items'::regclass; |
看固化参数 |
| 看表 / 索引大小 | SELECT pg_relation_size('items'); |
容量规划 |
| 删表 / 删扩展 | DROP TABLE items; / DROP EXTENSION vector; |
后者 ⚠️ 高危,先备份 |
| 端口 / 路径 | 值 | 备注 |
|---|---|---|
| PG 端口 | 5432 | 通用默认,以实际配置为准;pgvector 无独立端口 |
| 扩展 SQL | $(pg_config --sharedir)/extension/vector*.sql |
以 pg_config 输出为准 |
| 共享库 | $(pg_config --pkglibdir)/vector.so |
以 pg_config 输出为准 |
| 数据 / 索引 | PGDATA |
纳入现有 PG 备份 |
| 日志 | PG log_directory |
无独立日志 |
11. 参考与延伸
官方链接:https://github.com/pgvector/pgvector (含 README / CHANGELOG / LICENSE)。官网、独立文档站、镜像仓库、SDK、控制台 URL 官方资料未提供,勿臆测。
与同册其他产品的关系:已有 PG → 本篇;已有 ES / OpenSearch → Elasticsearch-OpenSearch.md;已有 Redis → Redis-Vector-Search.md;已有 ClickHouse → ClickHouse.md;已有国产关系库 → 国产数据库向量能力.md;规模超单机、需分布式专用向量库 → 01-专用向量数据库 分册。
进阶阅读:官方 README 的 HNSW / IVFFlat 参数与索引选项;CHANGELOG 中 0.8.x 修复项;PostgreSQL 的 EXPLAIN、GUC、MVCC、分区表与流复制文档。
本篇「未核实 / 以官方为准」事项:
- PostgreSQL License 官方 LICENSE 正文未直接核验,条款以官方仓库 LICENSE 文件为准。
- 0.8.0 / 0.8.1 / 0.8.3 / 0.8.4 / 0.9.0 的具体发布日期未核实(官方资料仅给 0.8.7、0.8.6 日期)。
hnsw.iterative_scan/ivfflat.iterative_scan的取值枚举与默认值官方未明确,只强调「过滤场景必须开启」。lists、ivfflat.max_probes的默认值未核实。- 除
vector_l2_ops外,其他距离对应的 opclass 名称官方未明确。 halfvec4000 维口径(可索引 / 存储是否区分)与sparsevec维度上限未核实。- 官网 / 文档站 / 镜像仓库 / SDK / 控制台 URL 官方资料未提供,勿臆测。
- 规模与 QPS、容量公式、告警阈值均为经验值,非官方承诺,须实测。
- PG 端口 5432、
psycopg客户端方法、pg_config/pg_stat_*属通用知识与经验性表述,以实际环境与所用驱动文档为准。