跳转到内容

PGVector 向量数据库教程大纲

当关系型数据库遇上向量搜索——PostgreSQL + pgvector,用你最熟悉的 SQL 做语义检索


📖 教程概述

为什么要在 PostgreSQL 上做向量搜索?答案很简单:你已经有 PostgreSQL 了。绝大多数后端系统的关系型数据库就是 PostgreSQL——用户表、订单表、商品表都在里面。当你需要给系统加上语义搜索能力时,与其引入一个全新的向量数据库(Chroma、Milvus、Qdrant),不如直接在现有的 PostgreSQL 上装一个 pgvector 扩展——零额外运维、零数据迁移、SQL 原生查询、事务一致性全保留。

pgvector 是 PostgreSQL 的向量相似度搜索扩展,它把向量(embedding)作为一等公民引入了 SQL 世界。你可以在同一张表里同时存储结构化字段(用户名、价格、日期)和向量字段(文本的 embedding),然后用一条 SQL 同时做结构化过滤和语义搜索——这是独立的向量数据库很难做到的。

本教程分为两大部分:前两章带你快速掌握 PostgreSQL 的核心操作(如果你已经熟悉 PostgreSQL 可以跳过),后五章深入 pgvector 的方方面面——从安装配置到向量索引、从 CRUD 到高级查询、从 RAG 实战到生产调优。我们不只讲 SQL 语法,更要理解 pgvector 在 RAG 架构中的独特优势、它与独立向量数据库的取舍、以及如何用"SQL 思维"重新理解向量搜索。


🗺️ 章节规划

第1章:PostgreSQL 基础入门

1.1 PostgreSQL 是什么?为什么 RAG 工程师需要它

  • 关系型数据库的核心价值:结构化数据存储、SQL 查询、ACID 事务、丰富的数据类型
  • PostgreSQL 在 AI 应用中的角色:不只是"存用户数据的数据库",更是 RAG 系统的结构化数据底座
  • PostgreSQL vs MySQL vs SQLite:为什么 pgvector 只支持 PostgreSQL(扩展机制、类型系统、索引架构的差异)
  • RAG 场景下 PostgreSQL 的独特优势:结构化数据 + 向量数据在同一张表中,一条 SQL 同时做 WHERE 过滤和向量搜索

1.2 安装与连接

  • 安装方式:Docker(推荐开发)、Homebrew(macOS)、apt/yum(Linux)、云托管(RDS/Aurora)
  • Docker 一键启动docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=xxx pgvector/pgvector:pg16
  • 连接方式:psql 命令行 / pgAdmin GUI / Python(psycopg2 / asyncpg) / Node.js(pg)
  • 基本连接参数:host、port、database、user、password
  • 连接池的概念:为什么生产环境不用短连接

1.3 SQL 基础:增删改查

  • CREATE TABLE:数据类型(INTEGER, VARCHAR, TEXT, TIMESTAMP, JSONB, BOOLEAN)、约束(PRIMARY KEY, NOT NULL, UNIQUE)
  • INSERT:单条插入、批量插入、COPY 命令高效导入
  • SELECT:基本查询、WHERE 条件、ORDER BY 排序、LIMIT/OFFSET 分页
  • UPDATE:更新字段、条件更新、RETURNING 子句
  • DELETE:条件删除、TRUNCATE 清空表
  • Python 操作 PostgreSQL:psycopg2 的基本用法(连接、游标、参数化查询、事务控制)

第2章:PostgreSQL 进阶必备

2.1 索引与查询优化基础

  • 为什么需要索引:全表扫描 vs 索引扫描的性能差异
  • B-tree 索引:PostgreSQL 的默认索引类型,适合等值查询和范围查询
  • 索引类型全景:B-tree / Hash / GIN / GiST / BRIN / SP-GiST,各自的适用场景
  • EXPLAIN ANALYZE:读懂查询计划,找到性能瓶颈
  • 索引设计原则:选择性高的字段优先、联合索引的列顺序、避免过度索引

2.2 JSONB 与半结构化数据

  • JSONB vs JSON:二进制存储、支持索引、查询性能对比
  • JSONB 查询操作符-> / ->> / ? / @> / ?|
  • GIN 索引加速 JSONB 查询CREATE INDEX idx_meta ON docs USING GIN (metadata)
  • JSONB 在 RAG 中的用途:存储文档的灵活 metadata(来源、标签、分类),无需预定义 schema

2.3 事务与并发控制

  • ACID 事务:BEGIN / COMMIT / ROLLBACK 的基本用法
  • 隔离级别:READ COMMITTED(默认)、REPEATABLE READ、SERIALIZABLE
  • MVCC 机制:多版本并发控制如何实现读写不互斥
  • 行锁与表锁:SELECT FOR UPDATE、 advisory locks
  • 为什么事务对 RAG 重要:文档入库时保证结构化数据和向量数据的原子性

第3章:pgvector 入门——向量扩展初体验

3.1 pgvector 是什么?它解决了什么问题

  • pgvector 的定位:PostgreSQL 扩展,不是独立的向量数据库
  • pgvector vs 独立向量数据库
    • pgvector 优势:SQL 原生、事务一致性、结构化+向量混合查询、零额外运维
    • pgvector 劣势:超大规模性能不如 Milvus、向量算法不如 FAISS 丰富
  • pgvector 的核心能力:向量存储(vector 类型)、距离计算(L2/Cosine/IP)、近似索引(IVFFlat/HNSW)
  • 版本与兼容性:pgvector 0.7.x、PostgreSQL 12~16 支持、Docker 镜像 pgvector/pgvector

3.2 安装 pgvector 与 Hello World

  • 安装方式:Docker(最简)/ CREATE EXTENSION(已有 PG 实例)/ 编译安装
  • Docker 一键启动docker run pgvector/pgvector:pg16
  • 创建扩展CREATE EXTENSION vector;
  • 第一个完整示例
    • 建表(id, content, embedding vector(3))
    • 插入向量数据
    • <-> 操作符做 L2 距离搜索
    • <=> 操作符做 Cosine 距离搜索
    • 理解返回结果的距离含义
  • Python 集成:psycopg2 + pgvector 库的 register_vector() 用法

3.3 vector 数据类型详解

  • vector(N):固定维度的向量类型,N 为维度(如 vector(384)、vector(1536))
  • 维度约束:同一列的所有向量维度必须一致,维度不匹配会报错
  • 向量字面量语法'[0.1, 0.2, 0.3]'::vector(3)
  • vector 类型的操作符
    • <->:L2 距离(欧氏距离)
    • <=>:余弦距离
    • <#>:内积距离(负内积)
    • + / -:向量加减
    • *:标量乘法
  • vector 类型的函数
    • vector_dims(embedding):获取维度
    • vector_norm(embedding):获取 L2 范数
    • l2_distance() / cosine_distance() / inner_product():显式距离函数

第4章:pgvector 的 CRUD 与混合查询

4.1 向量数据的增删改查

  • INSERT:插入单条/批量向量数据,pgvector 的 register_vector() 自动处理 Python list → PG vector 的类型转换
  • SELECT:查询向量字段、计算距离、按相似度排序
  • UPDATE:更新向量字段(如 embedding 升级后重新编码)
  • DELETE:删除向量数据、级联删除
  • 批量操作的性能优化:COPY 命令、UNNEST 批量插入、事务批处理

4.2 结构化 + 向量的混合查询(pgvector 的杀手锏)

  • 为什么混合查询是 pgvector 的核心优势:独立向量数据库需要两次查询(先向量搜索再结构化过滤),pgvector 一条 SQL 搞定
  • WHERE + ORDER BY 向量距离SELECT * FROM docs WHERE category = 'tech' ORDER BY embedding <=> '[0.1,...]' LIMIT 5
  • 多条件组合:时间范围 + 分类过滤 + 向量搜索
  • JSONB metadata + 向量搜索WHERE metadata @> '{"category": "faq"}' ORDER BY embedding <=> query_vec
  • 性能对比:pgvector 混合查询 vs Chroma where 过滤 vs Milvus 标量过滤

4.3 Python 完整 CRUD 封装

  • PGVectorManager 类:封装连接管理、CRUD 操作、批量操作
  • 参数化查询:防止 SQL 注入的最佳实践
  • 连接池配置:psycopg2.pool / asyncpg 连接池
  • 异步操作:asyncpg + pgvector 的高性能异步方案
  • ORM 集成:SQLAlchemy + pgvector 的使用方式

第5章:向量索引与性能优化

5.1 为什么需要向量索引

  • 暴力搜索的瓶颈:O(N×d) 的距离计算,10万条 768 维向量的全表扫描需要数百毫秒
  • 近似最近邻(ANN)的权衡:牺牲少量精度换取数量级的速度提升
  • pgvector 支持的两种索引:IVFFlat(倒排文件)和 HNSW(分层导航小世界图)

5.2 IVFFlat 索引

  • IVFFlat 原理:将向量空间划分为 K 个区域(聚类中心),搜索时只扫描查询向量附近的几个区域
  • 创建索引CREATE INDEX ON docs USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
  • lists 参数选择:√N(数据量的平方根)是经验起点,lists 过大/过小的影响
  • ** probes 参数**:搜索时扫描的区域数量,SET ivfflat.probes = 10;
  • IVFFlat 的局限:需要先有数据再建索引(聚类中心依赖数据分布)、索引构建慢、召回率受 probes 影响

5.3 HNSW 索引

  • HNSW 原理:多层图结构,从顶层向下导航,O(log N) 搜索复杂度
  • 创建索引CREATE INDEX ON docs USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 64);
  • m 参数:每层最大连接数,影响索引大小和召回率(默认 16,推荐 16~64)
  • ef_construction 参数:建索引时的搜索宽度,影响索引质量和构建速度(默认 64,推荐 64~200)
  • ef_search 参数:查询时的搜索宽度,SET hnsw.ef_search = 100;(默认 40,推荐 40~200)
  • HNSW vs IVFFlat 对比
    维度IVFFlatHNSW
    构建速度
    查询速度快(probes 适中时)更快
    召回率依赖 probes更稳定
    内存占用大(2~3x 数据量)
    增量更新需重建索引支持增量
    推荐场景数据量大且稳定数据量中等且频繁更新

5.4 索引选型与调优实战

  • 何时建索引:数据量 < 10K 不需要索引(暴力搜索足够快)
  • 索引类型选择决策树:数据量 / 更新频率 / 召回率要求 / 内存预算
  • 距离操作符与索引的对应关系
    • vector_l2_ops → L2 距离(<->
    • vector_cosine_ops → 余弦距离(<=>
    • vector_ip_ops → 内积距离(<#>
    • ⚠️ 索引创建时指定的 ops 必须与查询时使用的操作符一致!
  • EXPLAIN ANALYZE 诊断:确认索引是否被使用、扫描行数、实际耗时
  • 性能基准:不同数据量/维度/索引类型的 QPS 和 Recall@K 对比

第6章:pgvector 在 RAG 系统中的实战

6.1 RAG 架构中 pgvector 的角色

  • pgvector vs Chroma 在 RAG 中的定位差异
    • Chroma:纯向量数据库,适合快速原型
    • pgvector:关系型数据库 + 向量能力,适合需要结构化数据和事务一致性的生产系统
  • pgvector 的独特优势
    • 结构化数据 + 向量数据在同一张表 → 无需数据同步
    • SQL JOIN 能力 → 文档表 + 用户表 + 向量表自由关联
    • 事务保证 → 文档入库和向量索引更新的原子性
    • 成熟的运维工具 → pg_dump、pg_stat_statements、pg_stat_activity
  • RAG 全链路中 pgvector 覆盖的环节:文档存储 + 向量索引 + 混合查询 + 来源溯源

6.2 端到端 RAG Demo:文档问答系统

  • 项目结构:数据加载 → 切分 → embedding → 入库 pgvector → 检索 → 生成
  • 表设计
    sql
    CREATE TABLE documents (
        id SERIAL PRIMARY KEY,
        source TEXT NOT NULL,
        category TEXT,
        content TEXT NOT NULL,
        embedding vector(384),
        metadata JSONB,
        created_at TIMESTAMP DEFAULT NOW()
    );
  • Python 完整实现
    • 文档加载与切分(递归字符级切分)
    • Embedding 编码(SentenceTransformers)
    • 批量入库(COPY / UNNEST 高效插入)
    • 混合查询(WHERE + ORDER BY embedding <=> query_vec)
    • Prompt 组装与 LLM 调用
  • 来源溯源:利用 SQL JOIN 关联文档表和用户表,在回答中引用来源

6.3 对话记忆与用户画像

  • 对话历史表设计:session_id / role / content / embedding / created_at
  • 长期记忆表设计:user_id / preference_key / preference_value / embedding
  • 混合检索:同时搜索文档库和记忆库,用 UNION 或 JOIN 合并结果
  • TTL 清理:利用 PostgreSQL 的定时任务(pg_cron)自动清理过期记忆

第7章:生产部署与进阶主题

7.1 生产部署方案

  • Docker Compose 部署:PostgreSQL + pgvector + 应用服务
  • 云托管方案:AWS RDS / Azure Database / 阿里云 RDS PostgreSQL(需确认 pgvector 扩展支持)
  • 连接池配置:pgbouncer(生产标配)、连接数规划
  • 备份与恢复:pg_dump / pg_restore / WAL 归档 / 时间点恢复(PITR)
  • 高可用方案:流复制(Streaming Replication)/ 逻辑复制 / Patroni 自动故障转移

7.2 性能调优与监控

  • PostgreSQL 核心参数调优
    • shared_buffers:共享缓冲区大小(建议物理内存的 25%)
    • work_mem:排序和哈希操作的内存(影响向量索引构建)
    • effective_cache_size:操作系统缓存估计(影响查询计划选择)
  • pgvector 专用参数
    • ivfflat.probes / hnsw.ef_search:搜索精度与速度的权衡
  • 监控工具
    • pg_stat_statements:慢查询分析
    • pg_stat_activity:连接和锁监控
    • pg_stat_user_indexes:索引使用率
    • Prometheus + postgres_exporter + Grafana 可视化
  • 常见性能问题与排查
    • 索引未被使用 → 检查操作符是否匹配、数据量是否太小
    • 查询越来越慢 → 检查表膨胀、索引膨胀、是否需要 VACUUM
    • 内存不足 → 调整 shared_buffers、work_mem

7.3 pgvector 的局限性与替代方案

  • 已知局限
    • 单机架构,不支持原生分布式(最大规模约 1 亿向量,取决于内存)
    • HNSW 索引全内存驻留,数据量大时内存消耗高
    • 向量维度上限 2000(pgvector 0.7.x)
    • 不支持量化索引(PQ/SQ),无法做向量压缩
    • 增量数据量大时 IVFFlat 索引需要重建
  • 何时该用 pgvector
    • 已有 PostgreSQL 基础设施,不想引入新组件
    • 需要结构化数据和向量数据的强一致性
    • 数据量 < 1000 万向量
    • 需要复杂的 SQL 查询能力(JOIN、子查询、窗口函数)
  • 何时该换
    • 数据量 > 1 亿向量 → Milvus
    • 需要分布式 → Milvus / Qdrant
    • 需要向量压缩(量化) → FAISS / Milvus
    • 需要多模态内置支持 → Weaviate
  • pgvector 与其他方案共存:小规模用 pgvector,大规模用 pgvector + Milvus 混合架构

🎯 学习路径建议

PostgreSQL 新手(2-3天):
  第1-2章 → 掌握 PostgreSQL 的基本操作和核心概念
  → 能用 Python 连接 PG、执行 CRUD、理解索引和事务

RAG 开发者(2-3天):
  第3-4章 → 掌握 pgvector 的安装、vector 类型、混合查询
  → 能用 pgvector 搭建完整的文档检索 pipeline

生产工程师(3-5天):
  第5-7章 → 掌握向量索引调优、部署方案、监控运维
  → 能让 pgvector 在生产环境中稳定高效运行

深度研究者:
  全部章节 → 理解 pgvector 的设计权衡
  结合 IVFFlat/HNSW 算法原理、PostgreSQL 索引架构、MVCC 机制深入理解

📚 与 Chroma 教程的对照阅读

如果你已经学过本系列的 Chroma 教程,以下是两个教程的核心对照:

概念Chromapgvector
数据模型Document (id/text/embedding/metadata)Table Row (id/content/embedding/metadata columns)
集合CollectionTable
距离度量创建时指定(hnsw:space)查询时选择操作符(<->/<=>/<#>)
过滤where (Python dict)WHERE (SQL)
索引自动 HNSW手动创建 IVFFlat/HNSW
事务完整 ACID
部署嵌入式 / DockerDocker / 云托管 RDS
适合规模< 10M 向量< 100M 向量(取决于内存)
核心优势零配置、Python 原生SQL 原生、事务一致性、混合查询

本大纲遵循以下写作原则:每节以白板式通俗介绍开场 → 深入原理与面试级知识点 → 配合代码示例("比如下面的程序...")→ 覆盖常见用法与误区 → 结尾总结要点衔接下一节。

基于 MIT 许可发布