
PostgreSQL 不是"把数据放进表格"的工具。它是一个可扩展的数据处理平台——既能管订单、账户这样的强结构化数据,也能处理 JSON 文档、地理位置、时间序列和向量。
这句话是我能想到的对 PostgreSQL 最准确的概括。
很多人对 PG 的第一印象是"功能很多",但说不清多在哪。这篇咱们从头捋一遍:PG 到底是什么、为什么强、适合什么场景、以及它不能做什么。
PostgreSQL 是一个开源的对象关系型数据库管理系统(ORDBMS)。
拆开说:
名字也有故事。它起源于加州大学伯克利分校的 POSTGRES 项目,由 Michael Stonebraker 教授领导。项目后来加入了 SQL 支持,曾叫 Postgres95,1996 年改名 PostgreSQL。现在大家日常还是叫 Postgres。
这段历史解释了它的设计取向:从一开始就不满足于实现基础关系表,而是希望数据库能理解更复杂的数据类型和关系,并允许用户扩展数据库本身。
如果你要跟一个人解释 PG 为什么强,讲这五条就够了:
PostgreSQL 对 ACID 的执行是出了名的严格。一次事务要么完整提交,要么完整回滚,绝不会有"执行一半"的中间状态。
核心机制是 WAL(预写日志):数据写入磁盘之前,描述这次修改的日志必须先持久化。数据库异常重启后,可以重放 WAL 把数据恢复到一致状态。
BEGIN;
UPDATE accounts SET balance = balance - 1000 WHERE id = 1;
UPDATE accounts SET balance = balance + 1000 WHERE id = 2;
INSERT INTO transfers (from_id, to_id, amount) VALUES (1, 2, 1000);
COMMIT;
这四条语句要么全部成功,要么全部回滚。转账扣款和入账绝不会只完成一个。
MVCC(多版本并发控制)是 PG 并发能力的基石。更新数据时会创建新版本并保留旧版本,让不同事务根据自己的快照读取合适的数据版本。
效果很直接:普通 SELECT 不会阻塞 UPDATE,UPDATE 也不会阻塞 SELECT。 读事务看到的是自己快照时刻的一致性数据,写事务可以继续生成新版本。
但要注意,MVCC 不是万能药:
PG 对 SQL:2023 标准的兼容度超过 90%。窗口函数、CTE、递归查询、FILTER 子句、GROUPING SETS——这些都是原生支持多年的功能。
写复杂 SQL 的时候感受最明显:PG 的语法干净,嵌套层数宽松,各种边界情况处理更符合直觉。不需要为了一个窗口函数去写三嵌套子查询。
除了常见的 int、varchar、date,PG 原生支持:
这意味着 PG 可以在一套系统里同时处理关系数据和半结构化数据,不用在 MySQL 和 MongoDB 之间二选一。
PG 的扩展能力不是简单的"装个插件",而是允许你扩展类型、函数、操作符、聚合、过程语言和索引访问方法。
常见扩展:
| 扩展 | 能力 |
|---|---|
| PostGIS | 地理空间类型、函数、空间索引——地图应用标配 |
| pgvector | 向量存储与相似度检索——AI/RAG 必备 |
| TimescaleDB | 时间序列自动分区与分析 |
| pg_trgm | 三元组模糊搜索 |
| pgaudit | 数据库审计 |
| pg_stat_statements | 查询性能分析 |
但"能放进数据库"不等于"都应该放进数据库"。高计算量、长时间运行、频繁访问外部网络的操作,通常更适合放在应用服务中。
不同查询的数据结构和匹配方式不同,不存在一种索引能搞定所有问题。PG 提供了完整的索引菜单:
| 索引类型 | 擅长什么 | 典型场景 |
|---|---|---|
| B-tree | 等值、范围、排序 | 主键、时间过滤、分页 |
| Hash | 等值比较 | 只走 = 的查询 |
| GIN | 一个值含多个元素 | JSONB、数组、全文检索 |
| GiST | 可扩展搜索树 | 几何、范围、最近邻、PostGIS |
| BRIN | 大块数据概括 | 超大时间序列表(索引大小仅为 B-tree 的 1%) |
| SP-GiST | 非均匀分布数据 | 空间数据、分区数据 |
-- GIN 索引加速 JSONB 包含查询
CREATE INDEX idx_products_attributes ON products USING GIN (attributes);
SELECT * FROM products WHERE attributes @> '{"color": "black"}';
但索引不是越多越好。每个索引都占用空间,增加写入成本。正确做法是按执行计划来。
JSONB 是 PG 的二进制 JSON 类型。它允许在关系表中保存结构可变的数据,同时继续使用事务、JOIN、约束和索引。
场景很典型:商品的核心字段(ID、价格、库存)用固定列,颜色、尺寸、设备参数等可变属性放在 JSONB 里:
CREATE TABLE products (
id bigint PRIMARY KEY,
name text NOT NULL,
price numeric(12,2) NOT NULL CHECK (price >= 0),
attributes jsonb NOT NULL DEFAULT '{}'
);
JSONB 支持字段访问、包含判断、路径查询和 GIN 索引。但它不是让表结构消失的理由。经常用于 JOIN、排序、约束的稳定字段,应保留为普通列。
PG 通过流复制把主库产生的 WAL 发送给备用库。备用库持续回放日志以保持接近主库的状态。
几种复制方式:
| 方式 | 复制内容 | 典型用途 |
|---|---|---|
| 物理流复制 | WAL 底层修改 | 同版本主备、只读副本、故障切换 |
| 同步复制 | 提交时等备用库确认 | 降低主库故障时的数据丢失风险 |
| 逻辑复制 | 按表级变更发布/订阅 | 选择性同步、迁移、跨版本场景 |
需要区分:复制不等于高可用。复制负责产生数据副本,高可用还需要健康检查、故障切换、脑裂防护。生产环境常配合 Patroni 或 repmgr。
复制也不等于备份。 误删除和错误更新同样会被复制到备用库。独立备份 + 定期恢复演练仍然是必需的。
| 场景 | 为什么适合 |
|---|---|
| 金融与账务 | 事务、约束、审计要求高 |
| SaaS 与企业应用 | 关系复杂,查询变化多 |
| 电商与内容平台 | 订单关系 + 灵活属性 |
| GIS 与位置服务 | PostGIS、空间函数 |
| AI 与语义检索 | pgvector + SQL 联合过滤 |
| 时间序列与 IoT | 分区、BRIN、TimescaleDB |
大多数常规 Web 应用两者都能完成。关键差异:
| 维度 | PostgreSQL | MySQL |
|---|---|---|
| SQL 与复杂查询 | 功能完整,复杂类型突出 | CRUD 与 Web 生态成熟 |
| 扩展体系 | 类型、函数、索引接口丰富 | 插件与存储引擎体系成熟 |
| JSON | JSONB 可索引,深度查询 | 原生 JSON + 相关索引 |
| 复制与 HA | 流复制+逻辑复制,灵活组合 | 主从+组复制,生态成熟 |
| 学习曲线 | 功能和调优选项较多 | 常规场景上手直接 |
如果系统依赖复杂 JOIN、地理空间、JSONB、向量检索或严格数据约束,PG 更合适。如果团队已有成熟的 MySQL 运维体系,业务主要是常规事务,迁移 PG 未必能自动获得收益。
PG 功能丰富,但它不是万能数据库。
| 误区 | 真实情况 |
|---|---|
| MVCC 解决所有并发 | 热点行更新仍锁冲突,长事务阻碍清理 |
| 索引越多越快 | 索引增加写放大和存储成本 |
| JSONB 可代替表设计 | 过度 JSON 化削弱约束和可读性 |
| 有副本就不会丢数据 | 异步复制有延迟,误操作也被复制 |
| PG 天然水平扩展 | 单实例写入仍受单机资源限制 |
连接数、内存、autovacuum、慢查询、备份恢复和版本升级仍然需要持续治理。
PostgreSQL 强在哪里?
它强在以可靠的关系型事务为底座,向上提供 MVCC、多种索引、JSONB、过程语言、自定义类型和扩展插件。它不是把每类数据库简单拼在一起,而是让不同数据能力仍能共享 SQL、事务、权限和查询优化器。
记住三层结构:
PostgreSQL 不只是一款功能很多的关系型数据库,而是一套以事务一致性为核心、能够随业务持续扩展的数据平台。它真正强大的地方,是在保持数据可靠的前提下,仍然给开发者足够大的建模和查询空间。
本文由老张整理编写。
系列文章: