在向量搜索领域,Faiss、Milvus、Elasticsearch 等专用引擎占据主流,但对于许多中小规模应用场景,引入一套全新的向量数据库意味着额外的运维成本和架构复杂度。PostgreSQL 作为最广泛使用的关系型数据库之一,通过 pgvector 扩展即可原生支持向量存储与相似度检索,让你在现有数据库架构上零成本扩展出向量搜索能力。
本文将从安装配置、数据建模、索引选择到查询优化,手把手教你用 pgvector 构建生产可用的向量检索方案。

pgvector 安装与启用
pgvector 以 PostgreSQL 扩展的形式安装,支持 PostgreSQL 12 及以上版本。以 Ubuntu 为例,安装步骤如下:
# 安装 pgvector 扩展
sudo apt install postgresql-16-pgvector
# 连接数据库并启用扩展
psql -U postgres -d mydb -c "CREATE EXTENSION IF NOT EXISTS vector;"
安装完成后,即可在数据库中使用 vector 数据类型。验证是否成功:
SELECT * FROM pg_extension WHERE extname = 'vector';
表结构设计与数据写入
pgvector 提供了 vector 类型来存储固定维度的浮点向量。以下是一个典型的文档语义检索场景的建表方案:
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
title TEXT NOT NULL,
content TEXT NOT NULL,
embedding vector(768) NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
向量维度需要与你使用的 Embedding 模型输出维度一致。常见的维度有:
- OpenAI text-embedding-3-small: 1536 维
- BGE-large-zh: 1024 维
- sentence-transformers/all-MiniLM-L6-v2: 384 维
- 通用 768 维模型(如 text-embedding-ada-002)
插入数据时,直接将 Python list 转换为 vector 字符串即可:
import psycopg2
import numpy as np
conn = psycopg2.connect(host="localhost", dbname="mydb", user="postgres")
cur = conn.cursor()
# 假设 embedding 是模型输出的 768 维向量
embedding = np.random.randn(768).tolist()
embedding_str = "[" + ",".join(f"{x:.6f}" for x in embedding) + "]"
cur.execute(
"INSERT INTO documents (title, content, embedding) VALUES (%s, %s, %s::vector)",
("示例文档", "这是一段测试内容", embedding_str)
)
conn.commit()

相似度查询与距离函数
pgvector 支持三种距离度量方式,适用于不同的搜索场景:
- L2 距离(
<->):欧氏距离,适合图像特征匹配 - 内积(
<#>):负内积,适合已归一化的向量 - 余弦距离(
<=>):1 – 余弦相似度,最常用于文本语义搜索
执行一次 Top-K 余弦相似度检索:
-- 查询与目标向量最相似的 10 篇文档
SELECT id, title, 1 - (embedding <=> $1::vector) AS similarity
FROM documents
ORDER BY embedding <=> $1::vector
LIMIT 10;
在 Python 中执行查询的完整示例:
import psycopg2
def search_similar(query_embedding: list, top_k: int = 10):
conn = psycopg2.connect(host="localhost", dbname="mydb", user="postgres")
cur = conn.cursor()
embedding_str = "[" + ",".join(f"{x:.6f}" for x in query_embedding) + "]"
cur.execute("""
SELECT id, title, 1 - (embedding <=> %s::vector) AS similarity
FROM documents
ORDER BY embedding <=> %s::vector
LIMIT %s
""", (embedding_str, embedding_str, top_k))
results = cur.fetchall()
conn.close()
return results
索引类型与性能优化
当数据量超过几千条时,暴力全表扫描会变得很慢。pgvector 提供了两种索引来加速搜索:
IVFFlat 索引适合中等规模数据集(几十万条),基于倒排文件思想将向量聚类分桶:
-- 先创建索引,lists 参数建议设为 rows/1000 的平方根
CREATE INDEX ON documents USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);
-- 查询时设置探查的桶数量,越大召回率越高但越慢
SET ivfflat.probes = 10;
HNSW 索引是 pgvector 0.5+ 新增的图结构索引,在召回率和查询速度上都优于 IVFFlat,推荐生产使用:
-- HNSW 索引,m 和 ef_construction 控制图的密度
CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 200);
-- 查询时设置搜索宽度
SET hnsw.ef_search = 40;

混合检索:向量搜索与条件过滤结合
pgvector 最大的优势在于可以与 SQL 的 WHERE 条件无缝结合,实现向量搜索与结构化过滤的混合查询,这在专用向量数据库中往往需要额外的预过滤机制:
-- 只搜索最近 30 天的文档,按类别过滤后取 Top-5
SELECT id, title, 1 - (embedding <=> $1::vector) AS similarity
FROM documents
WHERE created_at > NOW() - INTERVAL '30 days'
AND title LIKE '%机器学习%'
ORDER BY embedding <=> $1::vector
LIMIT 5;
实际生产中建议将过滤条件与 HNSW 索引配合使用。PostgreSQL 的查询规划器会自动决定先走索引还是先过滤,通常对高选择性条件先过滤再走向量索引效果更好。
总结
pgvector 为 PostgreSQL 带来了实用的向量搜索能力,其核心优势在于:
- 零额外基础设施:无需引入新的数据库组件,直接复用现有 PG 集群
- SQL 原生集成:向量检索与关系查询、事务、权限管理天然结合
- HNSW 索引:百万级数据量下仍可保持毫秒级响应
- 运维简单:备份、主从复制、监控等 PG 生态工具完全适用
对于数据量在千万级以下、团队已有 PostgreSQL 运维经验的场景,pgvector 是性价比最高的向量搜索方案。当数据规模突破亿级或需要极致的检索性能时,再考虑迁移到 Faiss 或 Milvus 等专用向量数据库也不迟。
汤不热吧