pgVector 为 PostgreSQL 增添向量能力
常见的向量数据库有:Milvus、Weaviate、Pinecone、Qdrant等,而通过开源插件 pgVector 可将 Postgresql 扩展成一个向量数据库,特别适合需要进行向量相似性搜索的场景,例如语义搜索、图像检索、推荐系统等。
安装与启用
- 下面以一台 Ubuntu 24.04 系统部署为例,规划如下:
| ip地址 | 配置 | OS版本 | PG版本 |
|---|---|---|---|
| 192.168.31.101 | 4C-16G-500GB | Ubuntu 24.04.3 LTS | PostgreSQL 17.10 |
- 安装 PostgreSQL 17.10
#.开始安装
cd /opt/
wget -c http://iso.sqlfans.cn/postgresql/postgresql-17.10.tar.gz
wget -c http://iso.sqlfans.cn/postgresql/install_pgsql_1710.sh
wget -c http://iso.sqlfans.cn/postgresql/config/17.10/my_pgsql.conf
bash install_pgsql_1710.sh /opt /data 1921
#.登陆测试
/opt/pgsql/bin/psql -h 127.0.0.1 -p 1921 -U postgres -d postgres -c "SELECT * FROM pg_shadow;"
#.登陆测试,dba_admin 密码为 cf_rB1NKCzbaQuPH
/opt/pgsql/bin/psql -h 192.168.31.101 -p 1921 -U dba_admin -W -d postgres -c "SELECT * FROM pg_shadow;"
- 安装扩展 pgVector 0.8.2,注意 pg_config 版本要与 pg 版本一致
#.配置pg_config
ln -sv /opt/pgsql/bin/pg_config /usr/bin/
pg_config --version
#.安装pgvector
cd /opt
apt install -y git
git clone --branch v0.8.2 https://github.com/pgvector/pgvector.git
cd pgvector
make && make install
- 启用 pgVector 扩展
#.登录postgres
/opt/pgsql/bin/psql -h 127.0.0.1 -p 1921 -U postgres -d postgres
--.创建扩展 pgvector
CREATE EXTENSION IF NOT EXISTS vector;
--.验证扩展是否安装成功
SELECT * FROM pg_extension WHERE extname = 'vector';
--.确认生效
SELECT '[1,2,3]'::vector;
向量数据类型
- pgVector 提供了一个名为 vector(n) 的数据类型(其中 n 是向量维度)用于存储高维向量(浮点数数组),最大支持 16,000 维 的向量
--.创建一个存储向量的数据表,假设嵌入向量是3维
DROP TABLE IF EXISTS documents;
CREATE TABLE documents (id bigserial PRIMARY KEY, embedding vector(3));
\d
--.插入测试数据
INSERT INTO documents (embedding) VALUES ('[1,2,3]'), ('[4,5,6]'), ('[4,0,5]');
SELECT * FROM documents;
- 另外,pgvector 0.7.0 版本引入了两种新数据类型 halfvec 和 sparsevec,主要用于优化向量存储和查询性能。halfvec 通过降低精度来减少存储,sparsevec则为高维稀疏数据设计。
--.半精度向量(节省存储)示例512维,省 50% 空间
CREATE TABLE images (id serial PRIMARY KEY, embedding halfvec(512));
--.稀疏向量(关键词权重)示例10万维
CREATE TABLE keywords (id bigserial PRIMARY KEY, embedding sparsevec(100000));
相似性搜索
- 向量的检索主要是通过向量的距离函数来计算两个向量的距离来进行检索,两个向量的距离越近表示两个向量相似度越高。pgvector支持的距离运算符如下:
| 距离运算符 | 相似度度量 | 说明 | 推荐场景 |
|---|---|---|---|
| <-> | 欧氏距离(L2 Distance) | 计算两个向量之间的直线距离 | 图像、音频、地理数据检索 |
| <#> | 内积(Inner Product) | 用于最大内积搜索 | 推荐系统、模型打分 |
| <=> | 余弦距离(Cosine Distance) | 比较向量方向,对向量长度不敏感 | 文本语义检索、跨语言向量匹配 |
| <+> | 曼哈顿距离(L1 Distance) | - | - |
| <~> | 汉明距离(Hamming Distance) | - | 二进制向量 |
| <%> | 杰卡德距离(Jaccard Distance) | - | - |
- 下面以 L2 距离为例,查询向量最近邻
解读:根据 score 的得分,就能查询出相近的向量,值越小代表越相似
postgres=# SELECT id,embedding,embedding <-> '[1,2,3]' as score FROM documents ORDER BY embedding <-> '[1,2,3]';
id | embedding | score
----+-----------+-------------------
1 | [1,2,3] | 0 #.这个为0则表示完全相近
3 | [4,0,5] | 4.123105625617661
2 | [4,5,6] | 5.196152422706632
- 下面以余弦距离为例,对向量进行检索
解读:score 代表余弦相似度的值,值越小代表越相似
postgres=# SELECT id,embedding,embedding <=> '[1,2,4]' as score FROM documents ORDER BY embedding <=> '[1,2,4]';
id | embedding | score
----+-----------+---------------------
1 | [1,2,3] | 0.00853986601633272 #.这个最小
2 | [4,5,6] | 0.05500701052621171
3 | [4,0,5] | 0.18208218809080368
- 非常适合“向量 + 结构化”的混合查询
SELECT d.id, d.embedding, p.content
FROM documents d
JOIN projects p ON d.id = p.project_id
WHERE p.status = 'ACTIVE'
ORDER BY d.embedding <=> '[1,2,4]'
LIMIT 10;
索引支持
- 选择正确的索引是发挥 pgVector 性能的关键。pgVector 主要支持两种索引:
- HNSW 索引:基于图的索引,适合高精度、高频查询场景(数据量<100万,频繁更新,对查询性能和实时性要求高),召回率高但构建时间长。
解读:针对 HNSW 索引,m = 16 表示每个节点连接 16 个邻居,默认值为 16,取值范围为 2~100。将该值设置为一个较高的数量,可以增加召回量,但也会显著增加索引生成时间,并可能影响查询性能。而 ef_construction 表示在索引中添加元素时,需要检查的近邻数。默认值为64,取值范围为4~100。增加该值可以增加召回量,但是会增加索引构建时间。该值必须至少是m的两倍。
--.L2欧氏距离
CREATE INDEX docs_hnsw_l2 ON documents USING hnsw (embedding vector_l2_ops) WITH (m = 16, ef_construction = 64);
--.内积
CREATE INDEX docs_hnsw_ip ON documents USING hnsw (embedding vector_ip_ops) WITH (m = 16, ef_construction = 64);
--.查看索引
SELECT * FROM pg_indexes WHERE tablename = 'documents';
--.设置查询参数
SET hnsw.ef_search = 40;
- IVFFlat 索引:基于倒排索引的索引,适合大数据量场景(数据量>1000万,批量导入,更新少),构建快但精度略低
解读:针对 IVFFlat 索引,海量数据(100万+)推荐 lists = 100 表示聚类为 100 个桶,数据量小则推荐(10-100)查询精度高
--.L2欧氏距离
CREATE INDEX docs_ivfflat_l2 ON documents USING ivfflat (embedding vector_l2_ops) WITH (lists = 100);
--.内积
CREATE INDEX docs_ivfflat_ip ON documents USING ivfflat (embedding vector_ip_ops) WITH (lists = 100);
--.查看索引
SELECT * FROM pg_indexes WHERE tablename = 'documents';
--.设置查询参数:查询时扫描的聚类数量,值越大召回率越高,速度越慢
SET ivfflat.probes = 10;
- 使用 EXPLAIN ANALYZE 分析执行计划
--.临时关闭顺序扫描测试索引
postgres=# SET enable_seqscan = OFF;
SET
--.分析执行计划
postgres=# EXPLAIN ANALYZE SELECT id,embedding,embedding <-> '[1,2,3]' as score FROM documents ORDER BY embedding <-> '[1,2,3]';
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------
Index Scan using docs_hnsw_l2 on documents (cost=8.02..12.06 rows=3 width=48) (actual time=0.042..0.047 rows=3 loops=1)
Order By: (embedding <-> '[1,2,3]'::vector)
Planning Time: 0.168 ms
Execution Time: 0.090 ms
能力边界与限制
- 性能上限:受限单节点架构,高并发(QPS万以上)或超大规模数据(百亿级向量)的性能可能弱于专用向量数据库(如 Milvus 的分布式架构)
- 索引类型有限:目前支持的索引类型(IVFFlat、HNSW 等)虽覆盖主流需求,但定制化能力不如专用数据库
- 存储效率:向量数据以原始浮点数存储(未压缩),存储占用较高(1024 维 float32 向量约 4KB/条),需结合分区、归档优化
pgVector vs Pinecone vs Milvus 选型对比:
| 维度 | pgVector | Pinecone | Milvus |
|---|---|---|---|
| 部署复杂度 | ⭐ 极低(Postgres扩展) | ⭐⭐ 低(SaaS) | ⭐⭐⭐⭐ 高(K8s集群) |
| 运维成本 | 复用 DBA 团队 | 无(全托管) | 需专职运维 |
| 扩展上限 | ~1000万向量(单机) | ~10亿(自动扩展) | ~1000亿(分布式) |
| 查询性能 | 中等(单线程查询) | 高(专用优化) | 极高(并行查询) |
| 功能丰富度 | 基础 ANN + SQL 生态 | 中等(托管限制) | 极高(GPU、稀疏向量等) |
| 事务支持 | ⭐⭐⭐⭐⭐ 完整 ACID | ⭐⭐ 最终一致 | ⭐⭐⭐ 可调一致性 |
| 混合查询 | ⭐⭐⭐⭐⭐ SQL 原生 | ⭐⭐⭐ 元数据过滤 | ⭐⭐⭐⭐ 表达式过滤 |
| 成本(大规模) | 低(自建硬件) | 高(按量付费) | 中(自运维优化) |
| 适用场景 | 已有 PG、中小规模、复杂事务 | 快速启动、无运维团队 | 超大规模、极致性能 |
| 关键记忆点 | 最简集成 | 最快上手 | 最强扩展 |
选型决策树:
已有 PostgreSQL 且数据量 < 1000万?
├─ 是 → pgvector(零额外成本)
└─ 否 → 需要复杂 SQL 事务?
├─ 是 → Milvus + 外部事务系统,或分库架构
└─ 否 → 需要立即启动无运维?
├─ 是 → Pinecone
└─ 否 → Milvus(长期成本更优)