这不是 PostgreSQL 操作手册,而是一张概念地图。
目标:理解 PG 的设计取向、AI 时代它为什么重新被关注、和 MySQL 的关键差异,以及选型时到底在取舍什么。
版本坐标:PostgreSQL 18(2025-09 稳定版)、PG 19(2026-10-15 进入 RC1)、pgvector 0.8.x;MySQL 9.x 作对照。
1. 先理解 PG 的「性格」
PostgreSQL 常被形容为「学院派数据库」。这句话不是贬义,它描述的是设计取向:
| 维度 | PostgreSQL | MySQL |
|---|---|---|
| 核心气质 | 标准、严谨、可扩展 | 简单、直接、OLTP 优先 |
| SQL 能力 | 复杂查询、CTE、窗口、LATERAL、数组/范围类型 | 8.0 之后补齐 CTE/窗口,但类型和查询能力更克制 |
| 扩展方式 | 扩展(extension)生态 | 插件/存储引擎生态 |
| 典型强项 | 复杂查询、JSONB、地理、全文、向量、分析型负载 | 简单 CRUD、读多写少、成熟运维体系 |
| 典型弱项 | 运维复杂、VACUUM/膨胀、连接数需要池化 | 复杂查询/高级类型/扩展能力相对弱 |
一句话:
PG 想做一个「什么都能装」的通用数据库;MySQL 想做一个「把 OLTP 做稳」的数据库。
理解这句话,后面的差异就都能串起来。
2. AI 时代,PG 为什么又火了
2.1 向量不再是「另一个数据库」
过去做 RAG,常见架构是:
业务数据 → MySQL
向量数据 → Milvus / Qdrant / 专用向量库
两套存储意味着:
- 双写一致性:业务数据更新了,向量库可能还没更新;
- 无法在一条 SQL 里同时做「按租户过滤 + 按权限过滤 + 向量相似度排序」;
- 多一套部署、监控、备份、权限体系。
pgvector 把向量变成 PostgreSQL 的一种列类型:
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE doc_chunks (
id bigserial PRIMARY KEY,
tenant_id bigint NOT NULL,
content text NOT NULL,
embedding vector(1536) NOT NULL
);
CREATE INDEX ON doc_chunks
USING hnsw (embedding vector_cosine_ops);
SELECT id, content
FROM doc_chunks
WHERE tenant_id = 42
ORDER BY embedding <=> :query_vec
LIMIT 10;
这段 SQL 的关键不是 <=>,而是 WHERE tenant_id = 42 和向量排序在同一个事务、同一个查询里完成。
对 AI 应用来说,这解决的是:
- 业务数据和向量不会双写不一致;
- 租户隔离、权限过滤、软删除可以直接用 SQL 表达;
- 向量检索结果可以 JOIN 回业务表,拿到标题、权限、状态等元数据。
2.2 混合检索天然适合 SQL
RAG 的检索通常不是「纯向量」:
- 专有名词、编号、缩写,向量不如关键词;
- 语义相近但字面不同的内容,关键词不如向量;
- 还需要按时间、租户、权限、状态过滤。
PostgreSQL 同时具备:
tsvector/tsquery全文检索;pg_trgm模糊匹配;pgvector向量检索;- 普通 B-tree / GIN 索引和 WHERE 过滤。
所以可以在一个 SQL 里做「向量召回 + 关键词召回 + 元数据过滤」,再用 RRF(Reciprocal Rank Fusion)或业务权重合并。pgvector 的 README 里也给了和 Postgres 全文检索组合做 hybrid search 的示例。
这就是「一个数据库承担更多角色」带来的简化:少一套系统,就少一类一致性问题。
2.3 扩展生态:一个库装下更多东西
PG 的扩展生态是它和 MySQL 最大的气质差异之一:
| 扩展 | 作用 |
|---|---|
pgvector | 向量类型、HNSW/IVFFlat 索引 |
PostGIS | 地理空间类型和索引 |
TimescaleDB | 时序数据 |
pgmq | 基于 Postgres 的队列 |
pg_cron | 库内定时任务 |
pg_trgm | 模糊匹配 |
pgai | 在 SQL 里调用模型/生成 embedding(生态项目) |
不是说这些都应该塞进一个库,而是说:当你的需求还在中小规模时,PG 可以让你少引入几套中间件。
2.4 托管与开发者体验
AI 应用带火了一批「Postgres 作为后端平台」的产品:
- Supabase:Postgres + Auth + Storage + Realtime;
- Neon:Serverless Postgres、分支(branching);
- 云厂商:RDS / Aurora / Cloud SQL / Azure Database 都提供托管 PG。
对独立开发者和中小团队来说,「一个 Postgres 解决业务 + 向量 + 全文 + JSON」比「MySQL + 向量库 + 搜索服务」更容易起步。
2.5 但别把 PG 当成万能向量库
pgvector 很强,但不是所有场景都适合:
| 适合 | 不适合 |
|---|---|
| 向量规模和业务数据量在同一量级 | 十亿级向量、极高 QPS、严格低延迟 |
| 需要事务、JOIN、权限、租户过滤 | 需要专用向量库的分布式/量化/多副本能力 |
| 想减少系统数量 | 团队已经有成熟向量库运维体系 |
| 中小规模 RAG、语义搜索 | 大规模推荐/召回,需要极致召回与吞吐 |
工程上还要注意:
- HNSW 索引构建慢、占内存;数据量大时要单独评估
maintenance_work_mem、索引构建时间和内存; - 近似索引 +
WHERE过滤时,过滤是在索引扫描之后做的,可能返回不足 K 条;pgvector 0.8+ 支持 iterative index scans 来缓解; - 大表更新会带来膨胀和 VACUUM 压力;
- 连接数不是无限的,生产环境通常要 PgBouncer 之类的连接池。
结论:pgvector 适合「向量是业务数据的一部分」;专用向量库适合「向量本身就是核心负载」。
3. pgvector 的核心概念
3.1 类型和距离
| 类型 | 用途 |
|---|---|
vector(n) | 单精度向量,最常见 |
halfvec(n) | 半精度,省内存,最高 4000 维 |
bit(n) | 二值向量,配合汉明/Jaccard 距离 |
sparsevec(n) | 稀疏向量,最多 1000 个非零元素 |
常用距离操作符:
| 操作符 | 距离 |
|---|---|
<-> | L2 / 欧氏距离 |
<#> | 负内积 |
<=> | 余弦距离 |
<~> | 汉明距离(bit) |
<%> | Jaccard 距离(bit) |
3.2 HNSW vs IVFFlat
| 维度 | HNSW | IVFFlat |
|---|---|---|
| 结构 | 多层图 | 聚类倒排列表 |
| 查询性能 | 通常更好 | 较低 |
| 构建速度 | 慢 | 快 |
| 内存 | 更高 | 较低 |
| 是否需要训练 | 不需要 | 需要,最好先有数据 |
| 关键参数 | m、ef_construction、ef_search | lists、probes |
一个常见起点:
CREATE INDEX ON doc_chunks
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
SET hnsw.ef_search = 100;
ef_search 越大,召回越高、延迟越大;m 越大,图越密、内存和构建成本越高。
3.3 过滤与迭代扫描
近似索引有个容易踩的坑:
SELECT id
FROM doc_chunks
WHERE tenant_id = 42
ORDER BY embedding <=> :query_vec
LIMIT 10;
如果 tenant_id = 42 只占全表的 1%,HNSW 先按向量扫索引,再过滤,可能扫了很多条才凑够 10 条。pgvector 0.8+ 提供 iterative index scans:
SET hnsw.iterative_scan = strict_order; -- 或 relaxed_order
它会自动多扫一些索引,直到凑够结果或达到上限。这是「向量 + 元数据过滤」场景必须知道的参数。
3.4 RAG 里各段的职责
文档 → 分块 → embedding → 存 PG(content + embedding + metadata)
↓
query → embedding → 向量召回 + 关键词召回 + 过滤
↓
rerank
↓
LLM
PG 负责的是「存、过滤、召回、JOIN 元数据」;rerank 和生成通常在外面做。不要把整条 RAG 链路都塞进数据库。
4. PG vs MySQL:五个关键差异
4.1 进程与连接模型
- PostgreSQL:每个连接一个后端进程(process-per-connection),共享
shared_buffers;连接多了进程和内存开销明显,生产环境常配 PgBouncer。 - MySQL:每个连接一个线程(thread-per-connection),可以配 thread pool;连接开销相对轻,但高并发下也要池化。
这影响的是连接数规划和故障隔离,不是单纯的性能数字。
4.2 存储与 MVCC
这是两者最核心的架构差异。
PostgreSQL:
- 表是堆表(heap),更新/删除会产生新的行版本;
- 旧版本留在堆里,由
VACUUM回收; - 索引和表分离,索引指向行版本;
- 长事务会阻止旧版本回收,导致表膨胀。
MySQL InnoDB:
- 表按主键组织成聚簇索引(clustered index);
- 二级索引存的是主键值,不是行地址;
- MVCC 通过 undo log + 事务版本判断实现;
- 旧版本由 purge 线程清理。
带来的直接后果:
| 问题 | PG | MySQL |
|---|---|---|
| 主键选择 | 普通 B-tree,主键不是物理顺序 | 聚簇索引,主键选择影响写入和二级索引 |
| 更新代价 | 产生新行版本,依赖 VACUUM | 原地更新 + undo,依赖 purge |
| 膨胀 | 表和索引都可能膨胀 | 主要关注 undo 和碎片 |
| 长事务 | 阻止 VACUUM,危害大 | 阻止 purge,危害也大 |
所以「PG 要不要经常 VACUUM」「MySQL 为什么建议自增主键」这类问题,根源都在存储模型,而不是调参技巧。
4.3 索引与类型
| 能力 | PostgreSQL | MySQL |
|---|---|---|
| 普通索引 | B-tree | B+Tree |
| 全文 | GIN + tsvector | FULLTEXT |
| 地理 | PostGIS / GiST | SPATIAL |
| JSON | JSONB + GIN | JSON + 生成列/多值索引 |
| 部分索引/表达式索引 | 支持 | 部分支持 |
| 数组/范围/枚举/自定义类型 | 支持 | 较弱 |
| 向量 | pgvector(HNSW/IVFFlat) | VECTOR 类型 + 距离函数 |
MySQL 9.x 也提供了 VECTOR 类型和向量函数,但截至 9.x 的官方 CREATE INDEX 语法,InnoDB 侧还没有像 pgvector 那样的 HNSW/IVFFlat 索引;大规模向量检索通常要依赖 HeatWave、外部向量库或社区扩展。具体以你使用的版本和云厂商为准。
JSON 的差异也值得单独说:
- PG 的
JSONB是二进制存储,支持 GIN 索引、包含/存在操作符、路径查询; - MySQL 的
JSON也支持路径查询,但复杂索引通常要建生成列,再在生成列上建索引。
4.4 事务、DDL 与隔离级别
- PG 支持事务性 DDL:
BEGIN; ALTER TABLE ...; ROLLBACK;可以回滚; - MySQL 8 有 atomic DDL,但 DDL 仍会隐式提交,不能像 PG 那样把 DDL 放进事务里回滚;
- 默认隔离级别:PG 是 READ COMMITTED,MySQL InnoDB 是 REPEATABLE READ;
- 两者都支持 MVCC,但快照和锁的实现不同,MySQL 在 RR 下还有 gap lock/next-key lock 带来的死锁场景。
4.5 复制、扩展与运维
| 维度 | PostgreSQL | MySQL |
|---|---|---|
| 复制 | WAL 流复制 + 逻辑复制 | binlog(row/statement)+ GTID |
| 高可用 | Patroni、pg_auto_failover、云托管 | MHA/Orchestrator、Group Replication、云托管 |
| CDC | 逻辑复制/decoding、Debezium | binlog + Canal/Debezium,生态成熟 |
| 扩展 | extension(GIN/GiST/PostGIS/pgvector…) | 插件/存储引擎 |
| 运维难点 | VACUUM/膨胀、连接池、参数多 | 主从/GTID、在线 DDL、锁 |
两者都能做高可用和 CDC,差别更多在团队经验和生态,而不是「谁能谁不能」。
5. 选型:什么时候 PG,什么时候 MySQL
| 场景 | 更适合 |
|---|---|
| 复杂查询、分析型 SQL、CTE/窗口/LATERAL 用得多 | PG |
| 强 JSON 查询、JSONB + GIN 索引 | PG |
| 地理、全文、向量、扩展生态 | PG |
| 需要事务性 DDL、强约束、丰富类型 | PG |
| 标准 CRUD、读多写少、Schema 简单 | MySQL |
| 团队已有成熟 MySQL 运维体系 | MySQL |
| 云厂商/托管服务只支持 MySQL | MySQL |
| AI 应用:向量 + 业务数据要 JOIN/事务/权限过滤 | PG + pgvector |
| 十亿级向量、极高 QPS、专用召回 | 专用向量库 |
一句话:
PG 适合「数据关系复杂、查询复杂、需要扩展」;MySQL 适合「访问模式简单、要稳、要省心」。
AI 时代 PG 变火,不是因为它突然变快,而是因为它恰好能用一个数据库解决「业务数据 + 向量 + 过滤 + 全文」这几件事。这不代表 MySQL 不行——如果你的业务就是标准 OLTP,MySQL 仍然是更简单、更成熟的选择。
6. 版本现状(简短)
- PostgreSQL 18(2025-09)是当前稳定版:异步 I/O、skip scan、
uuidv7()、虚拟生成列、OAuth 认证等。 - PostgreSQL 19 在 2026-10-15 进入 RC1:
REPACK CONCURRENTLY、逻辑复制免重启、并行 autovacuum 等;尚未 GA。 - pgvector 0.8.x:HNSW/IVFFlat、halfvec、bit/sparsevec、二值量化、iterative index scans、hybrid search 示例。
- MySQL 9.x:提供
VECTOR类型和向量函数,但原生 InnoDB 侧还没有 pgvector 那样的 ANN 索引;大规模向量检索要另做评估。
7. 理解自检
- PG 和 MySQL 的进程/连接模型有什么不同?为什么都要连接池?
- PG 的 MVCC 为什么需要 VACUUM?长事务为什么会造成膨胀?
- MySQL 的聚簇索引为什么影响主键选择?二级索引存的是什么?
- GIN、GiST、BRIN 分别适合什么?MySQL 对应能力是什么?
- JSONB 和 MySQL JSON 的索引方式有什么差异?
- PG 的事务性 DDL 和 MySQL 的 atomic DDL 是一回事吗?
- HNSW 和 IVFFlat 怎么选?
ef_search调大有什么代价? - 向量 +
WHERE过滤为什么会召回不足?iterative scan 解决什么? - 为什么 AI 应用会重新考虑 PG?pgvector 的边界在哪?
- 什么情况下 MySQL 仍然比 PG 更合适?