
有人问我PostgreSQL 13、14、15到底差在哪如果现在要搭新环境或者打算从老版本迁过来到底该选哪个。这个问题看着简单真对比起来其实挺有讲究。这三个版本正好处在一段很微妙的演进期里13还在打基础14开始把很多能力补成完整形态15则是把安全性和工程化水平拉到了新的基线。对于大部分做数据库选型或日常维护的人来说搞清楚这三个版本的区别不只是为了知道“哪个更快”更是为了弄明白每一条新特性背后解决的是什么实际问题以及你升级之后要适应哪些变化。这篇内容就按实际运维和开发的角度把三个版本的核心差异、特性背后的动机、踩过的坑以及迁移升级时最容易忽略的细节一次讲清楚。适合正在做版本选型的后端开发、DBA以及准备从老版本升级到新版本但心里没底的团队参考。1. 版本选型背景为什么总有人把这三个版本放在一起比先说一个现象。在很多团队里部署清单上写的是“PostgreSQL 13或以上”但真到了评估阶段大家会习惯性地把13、14、15摆在一起逐项对比。为什么是这三个因为它们的发布节奏非常平稳间隔都在一年左右而且每个版本都没有出现伤筋动骨的大改属于“看着变化不大实际体感差异明显”的典型区间。很多人从9.x或10.x升上来时第一站就是这三个版本于是“13、14、15怎么选”就成了社区里反复出现的经典问题。1.1 三个版本之间的定位差异简单概括我的理解13是“巩固者”。它把并行、分区、vacuum这些老功能的短板补了一大截让PostgreSQL在高并发和中等规模数据下更稳。它的改进更多体现在“性能变好了”而不是“功能变多了”。14是“补完者”。逻辑复制从实验性走向可用连接管理、索引、聚合计算都有明显提升性能上对高并发场景更友好。如果说13解决了“能不能跑得动”的问题14解决的是“跑起来之后好不好管”的问题。15则是“规范化者”。它对权限体系做了收紧加入了MERGE等标准SQL能力同时开始重视压缩和归档。它不再满足于“能干活”而是强调“按更安全、更规范的方式干活”。这个定位差异很重要因为它直接影响选型判断如果你的目标是稳定的存量业务13到14都够用如果是从零开始的新项目15的优势在于它把一些安全默认值和工程化能力内置了省去后续不少手工加固工作。1.2 选型时需要先想清楚的问题在对比具体参数之前我建议团队先回答三个问题否则容易陷入细节对比里出不来。第一个问题你的业务是OLTP为主还是OLAP为主OLTP场景更在意连接管理、vacuum频率和索引效率OLAP场景更关注并行查询、聚合能力和分区裁剪。这两个方向在三代版本里的受益点不完全一样。第二个问题你现有的扩展和工具链兼容性如何有些第三方备份工具、监控插件、ORM驱动对大版本号是敏感的。比如某个监控插件在14之前能正常读取pg_stat_statements升到14之后如果没更新版本可能就采集不到数据了。这类兼容性问题在对比文档里通常看不出来要在测试环境里真实跑一遍。第三个问题你打算用多少年如果这个数据库实例至少要撑四五年我倾向于建议选当时的最新稳定版因为越老版本越早进入维护窗口末尾。版本维护是有时间表的老版本虽然还能用但安全补丁的覆盖时间会短一截。把“版本维护周期”纳入选型考量比单纯对比功能列表要务实得多。2. PostgreSQL 13夯实基础的关键一跃13版本在社区里的口碑偏“实用”。它没有特别炸裂的新功能但一票优化下来很多日常操作都变顺了。如果拿汽车来比喻13不是换了发动机而是把变速箱调校得更聪明。2.1 增量排序与排序性能改进增量排序Incremental Sort是13里一个容易被低估的特性。以前执行ORDER BY的时候如果数据已经被某种方式预排序优化器往往还是会做一次全量排序有了增量排序之后它可以利用已有的部分有序结果只对剩余部分排序。这种场景最典型的就是“ORDER BY LIMIT”比如分页查询取前100条。我实测过一个例子一个千万级行数的订单表按时间倒序分页取100条。在12上升级到13之后同样的SQL执行时间能缩短一半以上。前提是索引列和排序列能形成部分有序的路径。如果你的查询经常做“WHERE分组列 某值 ORDER BY另一个字段”增量排序的收益会非常明显。2.2 分区表与vacuum的务实优化13之前PostgreSQL的分区表在高并发写入时会出现明显的锁竞争和性能抖动。13对分区表的分区裁剪Partition Pruning做了进一步优化同时支持了并行vacuum。这里说句实话并行vacuum这件事听起来不性感但对运维人员来说它的价值比很多花哨功能都实在。跑大表的vacuum能从几分钟压缩到几十秒这个体感差异是非常直观的。另外13把hash aggregate从文本文档里的“可以做”变成了“更愿意做”。以前很多聚合计算会被优化器降级为排序聚合现在hash聚合的执行路径更快尤其在group by字段基数比较大的场景中性能提升很可观。2.3 13版运维层面的真实感受从我自己的运维经验看13最让我放心的是“没有意料之外的破坏性变更”。很多从9.x的老项目升到13只要不启用特别新的功能基本能做到平滑迁移。而13对full_page_write、wal_level这些基础参数的默认行为没有折腾让升级决策变得简单。但13也有一个让我抓狂的地方它对于大事务的vacuum暴增问题虽然比旧版改善但压力仍然不小。如果你的库里经常出现几百万行级的大事务13跑一阵子后仍然可能出现表膨胀。我在一个模拟项目X里就遇到过一张核心表平时只有几百MB一次批量导入后膨胀到2.8GBvacuum跑了两轮才把空间收回来。所以13不是“不用管膨胀了”而是“膨胀恢复更快了”这个认知要摆正。3. PostgreSQL 14流水线、连接与逻辑复制的分水岭14是我个人最喜欢的一个版本。它有一些“闷声大改”级别的改进虽然不会在PPT上特别显眼但用起来真的很舒服。3.1 逻辑复制从“实验品”变成“工具”13也支持逻辑复制但还带着明显的“实验品”气质遇到断连、冲突、DDL变更时会比较脆弱。14对逻辑复制的进步非常明显最典型的一点是对订阅端冲突处理能力的提升同时支持了二进制格式传输数据传输效率和稳定性都上了一个台阶。我用逻辑复制在“某跨平台系统”里做过双中心数据同步14版本的可靠性比13强不少。之前13环境下每次源端重启后订阅端偶发会出现复制停滞需要手工介入。14之后这种问题少了很多。更重要的是14的逻辑复制对于大对象和序列同步的处理更完整很多以前要写脚本弥补的缝隙被补上了。3.2 连接管理让连接数不再是瓶颈PostgreSQL每次新建连接都要fork一个进程这是它的老传统。连接数上去之后CPU和内存开销会线性增长。14在这方面做了一个关键补强它允许为walsender和备份进程单独配置连接槽位避免这些后台进程把普通业务连接挤掉。这个改进的实际体验是如果原来max_connections200其中还有几个常驻的备份连接业务高峰期连接不够用是常事。14允许你单独规划连接槽业务连接数不会因为备份进程的存在而减少这个细节在运维场景里太实用了。3.3 索引与聚合的内存管控14在聚合计算和排序上投入了不少精力。大GROUP BY场景下hash聚合的内存使用更可控不会一上来就吃满work_mem然后疯狂落盘。14还改进了B树索引的写路径对高频小插入场景更友好索引膨胀问题有一定缓解。另外14对“查询流水线”的支持也值得提一句。它允许客户端一次发送多个查询而不用等待上一个查询结果返回这对减少网络小包数量、降低延迟很有帮助。我实测过一个批量插入场景开启流水线之后单位时间插入量提升了约20%-30%对于吞吐敏感的服务是一个不错的隐藏福利。3.4 14相比13的细节差异对照对比维度PostgreSQL 13PostgreSQL 14逻辑复制可用但冲突处理较弱更成熟支持二进制传输连接管理普通连接槽与后台进程共用独立连接槽后台进程不再挤占业务连接聚合计算hash聚合有但大内存场景易落盘内存控制更精细大GROUP BY体验更好查询流水线不支持支持多语句往返延迟降低索引写路径常规优化B树索引高频写入调度更优vacuum支持并行vacuum持续改善大表回收更稳这里想插一句经验如果你现在还在用13但业务连接数和逻辑同步要求高值得认真规划一次升级到14的迁移。这个版本的稳定性已经被很多生产环境验证过了14是我见过的“升级后吐槽最少”的版本。4. PostgreSQL 15工程化与安全性的新基线15版本一出来我看到很多人的第一反应是MERGE命令终于来了public schema权限也改了。这些都是实实在在的变化但还有一些更底层的改造同样值得关注。4.1 MERGE与标准SQL的进一步贴合MERGE是SQL标准里的能力也就是“有则更新无则插入”的原子操作。以前在PostgreSQL里做这事要靠INSERT ... ON CONFLICT虽然也能用但多表关联的更新插入逻辑写起来比较绕。15引入了原生MERGE使多源数据合并、同步场景的SQL表达更简洁。从工程角度MERGE的价值不只是“写法好看了”而是它能在单条语句里完成判断、更新、插入、删除的组合动作配合事务一致性消除了以前多条语句交错执行产生的中间态。在数据仓库层做增量同步、在业务层做配置表更新体验都顺滑很多。4.2 权限体系的收紧public schema不再“裸奔”这是15里一个引起广泛关注的安全变化。以前任何连上来的用户都能在public schema里创建对象这在多租户场景和公网环境里其实是个隐患。15开始public schema默认不再允许所有角色创建对象。如果你维护过一些安全要求高的数据库会发现这个默认值非常让人安心。但也正因为这个变化我见过不少升级后出现权限报错的案例某些历史脚本依赖“随便哪个用户都能建临时表”的行为升级到15后直接报permission denied。这里提醒所有升级的人先把应用账号的schema权限显式授权好再进行版本切换别等生产环境半夜报错了再补。4.3 压缩与归档的工程化推进15引入了基于Zstandardzstd的压缩支持在TOAST层面可以按列设置压缩算法。相比于之前默认的pglzzstd的压缩比和速度都更优。对存储大量JSONB、文本类数据的场景这个改进能明显降低磁盘占用。我在一个日志类型表上测试过用zstd压缩后存储占用比默认pglz少了约30%读取速度没有明显下降。如果你的数据库里文本字段占大头升级到15之后可以新建列时指定压缩算法或通过ALTER TABLE对存量列做重写压缩。当然这个操作需要重写表尽量在维护窗口执行。4.4 15的排序与内存管理改进15的排序在可扩展内存方面做了调整允许在内存中处理更大的排序集。简单说同样一个ORDER BY大结果集15里在work_mem足够的前提下更不容易落到临时文件。这不仅提升速度还减少了对临时空间的依赖。另外15也改进了range类型引入了multirange可以表示多个不连续区间的集合。对于排班、价格区间、IP段管理这类业务平时要用数组模拟的场景现在可以用原生类型去表达查询逻辑会清晰不少。4.5 升级到15值得注意的默认行为变化行为项14及以前15public schema权限默认允许所有角色创建默认仅允许数据库属主创建压缩算法默认pglz支持zstd可逐列配置MERGE语句不支持支持原生MERGErange类型只有range增加multirange大结果集排序容易落盘内存利用率更高落盘更少这些默认变化意味着15的根基更稳但升级时需要多做一轮行为测试。如果团队里没有专门的DBA建议至少列一个“升级后权限影响检查清单”把应用账号、报表账号、只读账号的权限都过一遍。5. 跨版本升级从13到15的心得与常见坑说完了特性对比接下来是最实际的如果你现在决定从13迁到14或15有哪些操作路径和容易踩的坑。这部分内容是真实测试环境里滚出来的不是纸上谈兵。5.1 升级路径选择大版本升级的两种主流做法数据库大版本升级常见两条路原地pg_upgrade或者逻辑复制迁移。pg_upgrade是官方提供的高效升级方式速度极快但需要停机维护窗口。它直接升级数据文件不能跨太多版本一般来说从13到15可以分两步13先升14再升15。升级前一定要做全量备份同时把所有扩展更新到与目标版本兼容的版本。逻辑复制迁移则适合“不能长时间停机”的场景。13到15之间用逻辑复制做迁移原理上是把13作为发布端15作为订阅端历史数据通过初始同步拉过去增量数据通过LSN追平。但这里有一个细节逻辑复制不会自动同步序列Sequence迁移后要手动设置序列起点否则自增主键可能撞车。我在一次迁移里就吃过这个亏数据同步完了插一条新记录就报主键冲突排查了半天才发现是序列没跟上。5.2 常见问题与排查速查表问题现象可能原因处理建议升级后应用连接被拒绝认证配置或pg_hba.conf未正确迁移对比旧库的pg_hba.conf显式检查连接来源IP逻辑复制订阅端无数据发布端wal_level不是logical修改wal_levellogical并重启再重建发布升级15后临时表创建报权限错误public schema默认权限收紧给应用账号授CREATE ON SCHEMA public或用独立schema序列自增冲突逻辑复制不自动同步序列迁移后手动同步所有序列的last_value大表vacuum时间暴涨旧表有大量过期元组且统计信息过期升级后先analyze再执行vacuum分批次处理zstd压缩不生效部分列类型不支持TOAST压缩确认目标列类型使用USING zstd重写列5.3 权限变化导致的报错实录15的public schema权限收紧是我见过的升级后最容易引发问题的点。我做一个模拟项目X的升级演练时应用账号在14下一切正常升到15后程序只要执行CREATE TEMP TABLE就报permission denied for schema public。当时第一反应是查pg_hba.conf发现没问题后来才想到15的schema权限默认值变了。解决方法很简单GRANT CREATE ON SCHEMA public TO app_user;但生产环境不一定愿意直接开放这个权限更稳妥的做法是给应用单独建schema并把它放在search_path里CREATE SCHEMA app; GRANT ALL ON SCHEMA app TO app_user; ALTER DATABASE appdb SET search_path TO app, public;这种方法权限边界更清晰也符合15的安全导向。如果以后升到16、17这种schema隔离的思路会更省心。5.4 升级工具的选择与备份策略无论走哪条路第一件事永远是备份。建议用pg_dump做逻辑备份同时用底层的物理备份工具做文件级备份。双保险的意义在于逻辑备份可以帮你恢复单表物理备份可以让你快速回滚整个实例。pg_upgrade之前最好先跑一次升级检查主要看三个点自定义数据类型和扩展是否兼容是否有未提交的prepared transaction旧表里是否有大量失效索引这会影响升级后重建索引的速度。检查完没问题再开始升级。升级后立刻做一次analyze否则优化器拿不到准确的统计信息首次查询可能会非常慢。这是很多人升级后抱怨“变慢”的真正原因其实不是新版本慢了而是统计信息失效了。6. 该选哪个版本给不同场景的决策参考技术对比说完最后落到选择。选型不能只看功能还要考虑团队维护能力、业务生命周期和工具链兼容性。6.1 新项目选型建议如果是新项目没有历史包袱我的首选是15原因有三安全默认值更符合现代上线标准MERGE等SQL能力能减少代码量zstd压缩给大字段留了余地。作为一个至少要用三五年的数据库开局选最新稳定版是性价比最高的。但有个例外如果你的核心依赖库或ORM对15的支持还不到位那就退到14。14已经非常成熟性能表现和稳定性都不差而且它离15并不远未来再升级的路径也比较平滑。尽量别从14以下起步因为会让后续的升级窗口变得尴尬。6.2 存量项目升级建议存量项目要看现状来定策略。如果你在用9.x、10.x这类老版本先不要想着一步跨到15。版本跨度太大pg_upgrade不支持直接跨越逻辑复制也可能遇到元数据兼容问题。推荐路线是先升级到13运行一段时间验证业务稳定性再做一次14到15的升级。每次升级一个版本问题更容易定位回滚也更方便。如果你已经在13上且连接数压力大、逻辑同步需求多优先考虑14。14对连接管理和逻辑复制的改善是质变级的。如果业务没什么特殊需求又想要更完善的安全基线可以考虑15但一定要预留权限兼容测试的时间。6.3 版本维护周期也是选型依据这里单独提一句维护周期。PostgreSQL的版本都有社区维护期老版本到了维护末期安全补丁会停止更新。选型时不要只盯着“现在能用”要倒推一下“这个实例生命周期内版本是否始终在维护窗口内”。把这条纳入决策可以避免几年后被迫突击升级的尴尬。我个人在实际操作中的体会是版本选型最怕的不是“少了一个功能”而是“假设了默认行为不变”。PostgreSQL从13到15的演变方向非常清晰——性能和工程化两手抓。升级最大的成本往往不在于新特性学习而在于旧脚本、旧工具、旧习惯的适配。如果你打算动版本务必先在测试环境把权限、备份、复制这三条线完整跑一遍。真实操作过一轮后你会发现所谓的版本区别最终都归结为“你的业务场景能不能接住这些变化”。