痛点
你在做 RAG、语义搜索或推荐系统,需要一个向量数据库。调研一圈:Pinecone 要钱、Milvus 太重、Chroma 只适合原型。团队已经有 PostgreSQL 集群在跑,运维体系成熟,监控备份一套全的。这时候再引入一个独立的向量数据库,意味着:多一套运维、多一份数据同步、多一个故障点。
核心矛盾:AI 应用需要向量检索,但你不想为了这一个能力再养一套基础设施。
pgvector 的答案很直接——给 PostgreSQL 装个扩展,原地升级为向量数据库。事务、权限、备份、高可用全部复用现有体系,零额外运维成本。
方案概览
pgvector 是 PostgreSQL 的开源扩展,核心能力:
| 能力 | 说明 |
|---|---|
| 向量存储 | 支持最高 16000 维向量 |
| 索引算法 | IVFFlat(适合中小数据集)、HNSW(适合大规模高性能场景) |
| 距离函数 | L2 欧氏距离、余弦相似度、内积 |
| SQL 原生 | 向量查询就是普通 SQL,和业务数据 JOIN、过滤无缝结合 |
| 事务安全 | 向量写入和业务写入在同一个事务里,数据一致性有保障 |
适用场景:百万到千万级向量、需要和结构化数据联合查询、团队已有 PG 运维经验。
实操步骤
第 1 步:安装 pgvector
Ubuntu/Debian(PostgreSQL 16):
# 安装扩展包
sudo apt install postgresql-16-pgvector
# 进入 psql 启用扩展
psql -U postgres -d your_database -c "CREATE EXTENSION IF NOT EXISTS vector;"
Docker 一行搞定:
docker run -d --name pgvector \
-e POSTGRES_PASSWORD=your_password \
-p 5432:5432 \
pgvector/pgvector:pg16
验证安装:
SELECT * FROM pg_extension WHERE extname = 'vector';
-- 看到一行记录说明已启用
第 2 步:建表 + 存储向量
以一个文档语义搜索场景为例:
-- 创建文档表,embedding 列存 1536 维向量(OpenAI text-embedding-3-small 输出维度)
CREATE TABLE documents (
id BIGSERIAL PRIMARY KEY,
title TEXT NOT NULL,
content TEXT NOT NULL,
embedding vector(1536),
created_at TIMESTAMPTZ DEFAULT NOW()
);
写入向量数据(Python 示例):
import psycopg2
from openai import OpenAI
client = OpenAI()
conn = psycopg2.connect("postgresql://postgres:your_password@localhost/your_database")
def embed_and_store(title: str, content: str):
# 生成 embedding
resp = client.embeddings.create(
model="text-embedding-3-small",
input=content
)
embedding = resp.data[0].embedding # List[float], 1536 维
# 写入 PG
with conn.cursor() as cur:
cur.execute(
"INSERT INTO documents (title, content, embedding) VALUES (%s, %s, %s)",
(title, content, embedding)
)
conn.commit()
# 使用
embed_and_store(
"K8s Pod 调度原理",
"Kubernetes 调度器通过 Predicates 过滤不满足条件的节点..."
)
第 3 步:创建 HNSW 索引
数据量超过 10 万条后,暴力扫描太慢,必须建索引:
-- HNSW 索引(推荐,查询快、召回率高)
CREATE INDEX ON documents
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 200);
-- 调整查询时的搜索范围(越大越准,越慢)
SET hnsw.ef_search = 100;
IVFFlat vs HNSW 选型:
| 指标 | IVFFlat | HNSW |
|---|---|---|
| 构建速度 | 快(需要数据先入库) | 慢(但支持增量插入) |
| 查询延迟 | 中等 | 低(通常 <10ms) |
| 召回率 | 依赖 lists 参数 | 高(>95%) |
| 内存占用 | 较低 | 较高 |
| 适合场景 | 数据不频繁更新 | 实时写入 + 查询 |
生产环境推荐 HNSW,除非内存紧张。
第 4 步:语义搜索查询
-- 查询最相似的 5 篇文档(余弦距离)
SELECT id, title, 1 - (embedding <=> $1::vector) AS similarity
FROM documents
WHERE created_at > NOW() - INTERVAL '30 days' -- 结合业务条件过滤
ORDER BY embedding <=> $1::vector
LIMIT 5;
Python 完整查询:
def semantic_search(query: str, top_k: int = 5):
# 生成查询向量
resp = client.embeddings.create(
model="text-embedding-3-small",
input=query
)
query_embedding = resp.data[0].embedding
with conn.cursor() as cur:
cur.execute("""
SELECT id, title, 1 - (embedding <=> %s::vector) AS similarity
FROM documents
ORDER BY embedding <=> %s::vector
LIMIT %s
""", (query_embedding, query_embedding, top_k))
return cur.fetchall()
# 使用
results = semantic_search("如何排查 Pod 启动失败")
for doc_id, title, score in results:
print(f"[{score:.3f}] {title}")
避坑指南
坑 1:不建索引就上生产
pgvector 默认走全表扫描(Seq Scan),10 万条以上查询延迟飙升。
解决: 数据量 > 1 万就建 HNSW 索引。建索引期间表不锁写,但会消耗大量内存和 CPU,建议在低峰期执行:
-- 限制建索引时的内存使用
SET maintenance_work_mem = '2GB';
CREATE INDEX CONCURRENTLY ON documents
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 200);
坑 2:向量维度选错,后期改不了
vector(1536) 一旦建表,维度就固定了。换模型(比如从 1536 维换到 3072 维)意味着要新建列或新建表。
解决: 建表时明确锁定 Embedding 模型,记在文档里。如果未来可能换模型,可以多建一列预留:
ALTER TABLE documents ADD COLUMN embedding_v2 vector(3072);
坑 3:忽略 ef_search 参数调优
HNSW 索引的查询精度和速度由 ef_search 控制。默认值 40 可能召回率不够。
解决: 根据业务需求调整:
- 要求高召回(如 RAG):SET hnsw.ef_search = 200;
- 要求低延迟(如实时推荐):SET hnsw.ef_search = 50;
可以用已知正确答案的测试集跑一轮 benchmark,找到延迟和召回的平衡点。
生产部署建议
-
内存规划:HNSW 索引常驻内存,1000 万条 1536 维向量 ≈ 60GB 索引内存。
shared_buffers至少给总内存的 25%,确保索引能缓存住。 -
监控指标:关注
pg_stat_user_indexes中 HNSW 索引的idx_scan和idx_tup_read,确认查询走了索引而非 Seq Scan。 -
备份无感知:pgvector 数据就是普通 PG 表,pg_dump、pg_basebackup、流复制全部原生支持,不需要额外备份策略。
-
高可用:主从复制的从库可以直接分担向量查询流量,读写分离和传统业务一模一样。
总结
| 维度 | pgvector | 独立向量数据库 |
|---|---|---|
| 运维成本 | 零额外(复用 PG 体系) | 多一套集群 |
| 数据一致性 | 事务保证 | 需要同步机制 |
| 联合查询 | SQL JOIN 原生支持 | 跨库查询复杂 |
| 性能上限 | 千万级(单机),更大需分区 | 亿级(分布式) |
| 学习成本 | 会 SQL 就会用 | 新 API、新概念 |
结论: 如果你的向量规模在千万级以下,且团队已有 PostgreSQL 基础设施,pgvector 是 ROI 最高的选择。不加服务器、不加运维、不加数据同步——装个扩展,写条 SQL,AI 应用的向量检索就有了。
别为了追新技术给自己找麻烦。用好手里的工具,才是工程师的核心竞争力。