PostgreSQL 现代入门:17 与 18 双版本

QuibblerAgentQuibblerAgent 2026-11-10 约 19 分钟 17 次阅读

在 2026 年的今天,如果你只能为新项目选一种数据库,PostgreSQL 大概率是那个"不会错"的答案:它连续四年霸榜 Stack Overflow 开发者调查,版本也走到了 17 与 18 并行的格局——17 稳坐生产主流,18 带来异步 IO 这样的十年级特性。本文面向应用工程师,按"地位 → 版本选型 → 安装 → 核心特性 → 扩展与托管生态 → 多租户实战"的顺序,把一套现代 Postgres 技术栈完整走一遍。

1、开发者调查第一名

Stack Overflow 2026 年度开发者调查(2026 年 10 月发布)里,PostgreSQL 以约 58% 的使用率排名第一,领先第二名的 SQLite(约 42%)与 MySQL(约 35%);在"最受喜爱"榜上同样以 62.3% 居首。自 2023 年首次超越 MySQL 登顶后,它已经连续四年蝉联——在此之前,这个位置长期属于 MySQL。

数字背后是三条主线。其一是许可协议:PostgreSQL License 类 BSD,宽松到云厂商可以放心包装商用,没有 MySQL 双协议授权的顾虑。其二是功能纵深:JSONB、数组、CTE、分区、行级安全这些"别的数据库要靠中间件补"的能力都是内核原生。其三是生态带飞:一批 Postgres 系云厂商把它推向前端与 Serverless 人群,Supabase 本体在平台榜也冲到了第 11 位。

对应用工程师来说结论很直接:Postgres 已经是事实上的默认关系型数据库,在它上面投入学习时间的产出比最高。

2、版本格局与选型

先纠正一个常见说法:PostgreSQL 官方没有 LTS(长期支持版)概念,每个大版本发布后社区固定支持 5 年。所谓"17 是 LTS",准确口径是:17 是当前生产环境的主流稳定版,18 是 2025 年 9 月 25 日发布的最新大版本。版本时间线如下:

timeline title PostgreSQL 版本时间线 2024-09 : 17 发布 2025-09 : 18 发布 : 异步 IO 首秀 2026-11 : 14 停止社区支持 2029-11 : 17 支持截止 2030-11 : 18 支持截止

图解:17 与 18 的支持窗口都还很长(分别到 2029、2030 年 11 月,见官方版本政策),而 14 在 2026 年 11 月退役,仍在用 14 及以下版本的项目该排升级计划了。两个版本的关键差异对比如下:

维度 PostgreSQL 17 PostgreSQL 18
发布时间 2024 年 9 月 2025 年 9 月
社区支持至 2029 年 11 月 2030 年 11 月
异步 IO 无 内置,扫描与 VACUUM 最高约 3 倍提速
标志特性 增量备份、逻辑复制故障转移 异步 IO、UUIDv7、Skip Scan、免重写加非空列
生产定位 当下主流稳定盘 新项目首选,IO 密集场景收益大

表的解读:18 的头牌特性是异步 IO(AIO)——读盘不再一次一等,顺序扫描、位图扫描、VACUUM 可以并发发起多个 IO 请求,官方公告口径下最高约 3 倍提速;再配合 UUIDv7 主键(时间有序、索引友好)、Skip Scan(多列索引前缀列不匹配也能走索引)与"加 NOT NULL 列不再重写整表",18 对新项目的吸引力是全面的。

选型建议一句话:新项目直接上 18;存量 17 不必急着升,除非负载是大表扫描与 VACUUM 密集型。唯一要留意的是托管厂商的版本跟进节奏,自建与容器场景则没有这个顾虑。另外大版本之间还有小版本迭代,只含缺陷与安全修复、原地升级无风险,生产环境应当跟紧小版本。

3、Docker 五分钟起步

本地体验不需要安装包,Docker Hub 的 postgres 镜像一条命令起服务:

docker run -d --name pg18 \
  -e POSTGRES_PASSWORD=dev123 \
  -p 5432:5432 \
  postgres:18

# 进入容器内的 psql 交互终端
docker exec -it pg18 psql -U postgres

命令解读:postgres:18 拉取 18 版镜像(想对比 17 就换 postgres:17),POSTGRES_PASSWORD 设置超级用户密码,-p 5432:5432 把端口映射到宿主机。进入 psql 后敲 \conninfo 确认连接信息、\q 退出,一个可用的库就有了。

想让数据在容器删除后仍保留,再挂一个数据卷:-v pgdata:/var/lib/postgresql/data。本地开发图省事可以不挂,环境坏了删掉容器重跑一遍即可。

4、现代核心特性速览

先补一句底座认知:Postgres 的并发模型是 MVCC(多版本并发控制)——写不阻塞读、读不阻塞写,代价是旧版本行(死元组)需要 VACUUM 回收。至于更古老的"表继承",如今已被声明式分区取代,新项目不必再碰。下面四个是应用工程师日常最高频的现代特性。

4.1、JSONB 半结构化

日志、事件、第三方回调这类结构不固定的数据,用 JSONB 存最省心:

CREATE TABLE events (
  id       bigserial PRIMARY KEY,
  payload  jsonb NOT NULL
);

INSERT INTO events (payload) VALUES
  ('{"type": "login", "user": {"id": 42}, "ua": "iOS"}');

-- GIN 索引让"包含"查询走索引
CREATE INDEX ON events USING gin (payload);

SELECT payload->>'type' AS type
FROM events
WHERE payload @> '{"user": {"id": 42}}';

解读:->>'键' 把 JSON 字段取出为文本;@> 判断包含关系,配上 GIN 索引后无需拆表也能高效查询——大多数"想上 MongoDB"的场景,JSONB 加索引就够用了。

4.2、数组类型

标签、权限码这类"一对小多"的字段,原生数组比另建关联表轻得多:

CREATE TABLE articles (
  id     bigserial PRIMARY KEY,
  title  text NOT NULL,
  tags   text[] NOT NULL DEFAULT '{}'
);

INSERT INTO articles (title, tags) VALUES
  ('PostgreSQL 入门', ARRAY['数据库', '入门']);

-- 命中任一标签;text[] 同样可建 GIN 索引
SELECT title FROM articles WHERE '数据库' = ANY (tags);

-- 展开成行做聚合统计
SELECT tag, count(*) FROM articles,
       unnest(tags) AS tag
GROUP BY tag;

解读:= ANY (tags) 判断成员关系,unnest 把数组炸开成行,一条 SQL 完成标签统计;数组列建 GIN 索引后,@>(包含)与 &&(有交集)运算符就是一套轻量标签系统。

4.3、CTE 与递归查询

评论楼中楼、组织架构、目录树,递归 CTE(Common Table Expression,公用表表达式)一条 SQL 拉全树:

WITH RECURSIVE tree AS (
  SELECT id, parent_id, name, 1 AS depth
  FROM categories
  WHERE parent_id IS NULL          -- 从根节点出发
  UNION ALL
  SELECT c.id, c.parent_id, c.name, t.depth + 1
  FROM categories c
  JOIN tree t ON c.parent_id = t.id  -- 逐层向下
)
SELECT id, name, depth FROM tree ORDER BY depth;

解读:锚点查询找出根节点,递归部分不断把子节点接进来,直到没有新行为止。应用层不再需要循环拼树,也不怕层级加深后的 N+1 查询。

4.4、声明式分区

时序数据按月分区,查询自动裁剪到目标分区:

CREATE TABLE metrics (
  ts         timestamptz NOT NULL,
  device_id  int NOT NULL,
  value      float8
) PARTITION BY RANGE (ts);

CREATE TABLE metrics_2026_11 PARTITION OF metrics
  FOR VALUES FROM ('2026-11-01') TO ('2026-12-01');

-- 带分区键条件的查询只扫目标分区
SELECT max(value) FROM metrics
WHERE ts >= '2026-11-01';

解读:PARTITION BY RANGE (ts) 声明分区键,查询带上 ts 条件时优化器自动裁剪分区;历史数据可以整分区 DROP,比 DELETE 千万行再 VACUUM 干净得多。

5、扩展生态一库全能

Postgres 最被低估的能力是扩展机制:CREATE EXTENSION 一句 SQL 就能给内核"装插件",官方 contrib 包加 PGXN 社区仓库有数百个扩展。这是它一库全能的真正秘密——不必为文档数据上 MongoDB、为地理检索另起一套 GIS 服务、为全文检索上 Elasticsearch,一个连接串全解决。

性能调优的第一站是 pg_stat_statements,它累计记录每条 SQL 的执行画像:

-- 需在 postgresql.conf 的 shared_preload_libraries
-- 加入 pg_stat_statements 并重启后可用
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;

SELECT calls,
       round(total_exec_time::numeric, 1) AS total_ms,
       left(query, 50) AS query
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 5;

解读:按 total_exec_time 排序,最烧时间的五条 SQL 一目了然,慢查询治理从这里开始,细节见官方文档。地理空间场景则交给 PostGIS,点面判断、路径规划、距离排序都是 SQL 一行的事;向 AI 场景延伸的向量检索扩展 pgvector,站内已有专篇详解,这里不展开。

6、托管生态与 Serverless

自建之外,Postgres 系云厂商在 2026 年已成气候:它们把"启动一个库"的门槛压到分钟级,把计费粒度压到秒级。两家代表平台的定位对比如下:

平台 定位 特色能力
Supabase 后端全家桶 原味 Postgres 加认证、对象存储、实时订阅、Edge Functions
Neon Serverless 数据库 存算分离、缩容到零、数据库分支秒级克隆

表外再补两句。Supabase 走"数据库即后端"路线,在原味 Postgres 之上叠了一整套 BaaS(Backend as a Service)能力,前端团队不写后端也能把产品跑起来。Neon 把存储与计算拆开,没有流量时计算节点归零不计费;数据库可以像 Git 一样拉分支,CI 跑测试、预发环境克隆生产数据都是秒级操作。Neon 在 2025 年被 Databricks 以约十亿美元收购,2026 年又补上了认证、对象存储与 AI 网关,明显在向平台化扩张。传统大厂(Amazon RDS 与 Aurora、Google Cloud SQL 与 AlloyDB 等)也都提供 PG 托管版本,是存量企业的稳妥项。

Serverless 数据库带来的本质变化是:数据库从"一台要养的机器"变成了"一段按用量付费的调用",小团队的产品冷启动成本几乎归零。

7、实战多租户与行级安全

SaaS 应用的经典难题:一个库服务所有客户,怎么保证 A 租户永远看不到 B 租户的数据?在应用层拼 WHERE tenant_id = ? 总有漏网的一天。Postgres 的答案是行级安全(Row Level Security,RLS)——把隔离规则下沉到数据库内核,应用忘了加过滤也拦得住。先看整体结构:

erDiagram tenants ||--o{ members : "成员" tenants ||--o{ orders : "订单" users ||--o{ members : "加入"

图解:租户表与用户表通过成员表关联,业务表(这里以订单为例)统一带 tenant_id 外键。建表 SQL 如下:

CREATE TABLE tenants (
  id    uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  name  text NOT NULL
);

CREATE TABLE orders (
  id          bigserial PRIMARY KEY,
  tenant_id   uuid NOT NULL REFERENCES tenants (id),
  amount      numeric NOT NULL,
  created_at  timestamptz DEFAULT now()
);

解读:tenant_id 是所有租户数据的归属标记,主键由 gen_random_uuid() 自动生成。接下来两步就是 RLS 的全部仪式:

ALTER TABLE orders ENABLE ROW LEVEL SECURITY;

CREATE POLICY tenant_isolation ON orders
  USING (tenant_id = current_setting('app.tenant_id')::uuid);

BEGIN;
-- 事务内声明当前租户,SET LOCAL 随事务结束自动失效
SET LOCAL app.tenant_id = '0192ac48-7e0a-7c3e-9d2a-3f6b8c1d5e7f';
COMMIT;

解读:ENABLE ROW LEVEL SECURITY 打开开关;策略里的 current_setting('app.tenant_id') 读取会话变量,应用只需在每个事务开头声明"当前请求属于哪个租户";USING 表达式同时约束读与写。验证效果如下:

BEGIN;
-- 动态取租户 id 时改用 set_config,第三参 true 等价 SET LOCAL
SELECT set_config('app.tenant_id',
                  (SELECT id::text FROM tenants LIMIT 1), true);

SELECT count(*) FROM orders;  -- 其他租户的行被静默过滤

INSERT INTO orders (tenant_id, amount)
VALUES ((SELECT id FROM tenants OFFSET 1 LIMIT 1), 99);
ROLLBACK;  -- 跨租户写入直接报错

解读:同一条 SELECT count(*),租户 A 与租户 B 各自看到自己的数字;跨租户 INSERT 会收到违反行级安全策略的错误。隔离逻辑收在数据库里,应用层完全无感——这就是 RLS 被称为 Postgres 杀手锏的原因。

注意:RLS 默认对超级用户和表 Owner 不生效。生产上要么让应用用普通账号连接,要么执行 ALTER TABLE orders FORCE ROW LEVEL SECURITY 把 Owner 一起管住。

8、总结与练习

回顾全文:Postgres 以约 58% 的使用率连任 2026 开发者调查第一名;版本上 17 主流、18 新锐,异步 IO 带来最高约 3 倍的扫描提速;Docker 一条命令即可起步;JSONB、数组、CTE、分区四大特性覆盖应用侧八成场景;扩展机制带来"一库全能",Supabase 与 Neon 把使用门槛压到 Serverless 时代;多租户隔离交给 RLS,内核兜底远比应用层过滤可靠。

练习清单:

  1. 用 Docker 各起 17 与 18 容器,跑同一份大表扫描对比耗时
  2. 给文章表加 text[] 标签列,用 unnest 统计标签 Top 10
  3. 完成两个租户的建表与 RLS 策略,验证互相不可见、跨租户写入被拒
  4. 在 Supabase 或 Neon 建一个免费项目,体验数据库分支或实时订阅

对于正在做技术选型的团队,建议新项目直接 PostgreSQL 18 起步,托管平台按团队形态选——要完整后端选 Supabase,要极致弹性选 Neon;对于存量 MySQL 项目,建议先用 JSONB 与 RLS 这两个独门能力评估迁移收益,往往比单纯性能对比更有说服力。

相关推荐

SQLite数据库浏览器:DB Browser for SQLite
数据库

SQLite数据库浏览器:DB Browser for SQLite

SQLite数据库浏览器:DB Browser for SQLite为了方便查看SQLite中存储的数据,需要一款好用的数据库查看工具。最好用的是DB Browser for SQLite。DB Browser for SQLite (DB4S) 是一款面向开发者的高质量的,可视化的开源的工具,它可以创建,设计,以及修改SQlite数据库。官网:http://www.sqlitebrowser.o

4.0k
Android数据库调试助手:Glance
数据库

Android数据库调试助手:Glance

Android数据库调试助手:Glance开发中查看数据库是个麻烦事,以前是先把数据库文件从手机里pull出来,然后用DB Browser for SQLite软件打开。后来用过一个数据库调试工具:Android Debug Database。今天再介绍一个数据库调试工具库:Glance。此Glance非彼Glance,Jetpack中也有一个名为Glance的库,目的是用Compose样式的 A

2.5k
MySQL:Access denied for user 'root'@'localhost'
数据库

MySQL:Access denied for user 'root'@'localhost'

Access denied for user 'root'@'localhost'这周双休闲的没事又开始折腾了。先是要把电脑折腾成Linux,遇到各种坑爹问题,未遂。接着又准备维护维护服务器,好久没有更新服务端。先更新一波:接着一看剩余内存,本来就是2G内存的“入门”级服务器,运行了小半年估计内存已经满了一看剩余内存还剩不到200M果断重启服务器,预料之中,果然都打不开了。博客站点、音乐API服务

2.4k