Christopher Winslett:Postgres 19:自我们撰写以来,我们的建议发生了哪些变化

Christopher Winslett:Postgres 19:自我们撰写以来,我们的建议发生了哪些变化

💡 原文英文,约3300词,阅读约需12分钟。
📝

内容提要

Postgres 19改进了异步I/O、COPY容错、LZ4默认压缩、BRIN索引和分区操作。建议保留COPY批量加载、jsonb存储、TOAST建模、索引权衡等核心原则,并利用新特性优化性能。升级后需用EXPLAIN重新测试计划,分区仍以生命周期管理为主。

🔎

延伸解读

升级后需重新验证执行计划

Postgres 19 默认关闭了 JIT,并引入了异步 I/O 等新特性,这可能导致查询执行计划发生变化。文章建议升级后使用 EXPLAIN (ANALYZE, BUFFERS, IO) 重新测试关键查询,尤其是大型分析或并行扫描场景。不要依赖旧版本的计划假设,新版本可能选择不同的索引或扫描路径,重新验证是确保性能不倒退的关键步骤。

COPY 容错选项的实际用法

Postgres 19 增强了 COPY 的容错能力,支持 ON_ERROR set_null 和 REJECT_LIMIT 等选项。set_null 可将无效字段置为 NULL 而保留整行,适合部分数据损坏的情况;ignore 则跳过整行,配合 REJECT_LIMIT 可限制跳过数量。文章提醒避免使用 '\N' 作为默认值哨兵,以免与 NULL 混淆,并建议查阅最终文档确认边界情况。

LZ4 默认压缩的升级影响

Postgres 19 将默认压缩算法从 pglz 切换为 LZ4,新写入的 TOAST 数据将自动使用 LZ4,但升级前已有的数据仍保持原算法。文章建议通过 pg_column_size 和 octet_length 对比存储大小,评估是否需要重写表以应用新压缩。若需重写,可使用原生 REPACK 命令,但需注意其需要主键或副本标识,且会占用约两倍磁盘空间。

分区操作的新工具与注意事项

Postgres 19 新增了 MERGE PARTITIONS 和 SPLIT PARTITION 命令,可直接在 SQL 中合并或拆分分区,但操作会持有 ACCESS EXCLUSIVE 锁,且会复制数据,适合维护窗口执行。对于在线操作,仍推荐使用 DETACH PARTITION ... CONCURRENTLY。此外,COPY TO 现在可直接作用于分区父表,简化了导出流程。

Q&A

Postgres 19 在异步 I/O 方面有哪些改进?

Postgres 19 在异步 I/O 方面进行了增强,包括 I/O 工作进程可以自动扩展(通过 io_min_workers 和 io_max_workers 参数),改进了预读调度,并且 EXPLAIN (ANALYZE, IO) 可以显示异步子系统的活动。这些改进使得顺序扫描、位图堆扫描和 VACUUM 等操作在冷存储或延迟较高的存储上性能提升,社区基准测试显示最高可达约 3 倍的性能提升。

Postgres 19 中 COPY 命令有哪些新功能?

Postgres 19 中 COPY 命令新增了多项功能:支持 ON_ERROR SET_NULL 选项,将无效值转换为 NULL 而不是丢弃整行;支持跳过多个头部行(HEADER 2);COPY TO 可以输出 JSON 格式(包括 FORCE_ARRAY 选项输出单个 JSON 数组),并且可以直接从分区表导出数据。此外,文本/CSV 解析通过 SIMD 加速,性能提升。

Postgres 19 中默认压缩算法改为 LZ4 有什么影响?

Postgres 19 将默认的 TOAST 压缩算法从 pglz 改为 LZ4。LZ4 压缩和解压速度更快,压缩率与 pglz 相近,并且对不可压缩数据能快速失败。这意味着新写入的 TOAST 值默认使用 LZ4 压缩,无需额外配置。但升级后已有的 TOAST 值仍保持原压缩算法,直到行被更新或重写。

Postgres 19 中 BRIN 索引有哪些改进?

Postgres 19 中 BRIN 索引本身没有重大新特性,但受益于异步 I/O 的改进,BRIN 索引扫描后的位图堆扫描性能提升。此外,Postgres 14 引入了 minmax_multi 操作符类,可以存储多个 min/max 值,处理异常值更好;Postgres 17 支持并行创建 BRIN 索引。因此,在 19 中,BRIN 索引对于相关性强、追加为主的数据仍然高效,并且有更多形状可选(经典 minmax、multi-minmax、Bloom)。

Postgres 19 中分区操作有哪些新功能?

Postgres 19 新增了原生 MERGE PARTITIONS 和 SPLIT PARTITION 命令,可以直接在 SQL 中合并或拆分分区。此外,COPY TO 可以直接从分区父表导出数据,无需使用 SELECT 包装。vacuumdb --analyze-only 默认分析分区父表。这些功能简化了分区管理,但 MERGE/SPLIT 需要 ACCESS EXCLUSIVE 锁,且不支持 CONCURRENTLY,因此建议在维护窗口执行。

Postgres 19 中 JIT 默认关闭,对性能有什么影响?

Postgres 19 中 JIT(即时编译)默认关闭,而之前从 Postgres 12 开始默认开启。旧的成本模型不可靠,导致大型分析查询或并行扫描可能被错误地编译,浪费资源。关闭后,这些查询将不再进行运行时编译,除非显式开启 jit 参数。如果依赖 JIT 加速,需要重新启用并重新测试计划。

Postgres 19 中 REPACK 命令有什么新特性?

Postgres 19 引入了原生 REPACK 命令,支持 CONCURRENTLY 选项,可以在不长时间锁定表的情况下重写表。REPACK (CONCURRENTLY, ANALYZE) 可以在表可读可写时重建堆,但需要主键或基于索引的副本标识,且不适用于分区父表。它需要约 2 倍表大小的磁盘空间,并且不是 MVCC 安全的(并发事务可能短暂看到表为空)。

Postgres 19 中 skip scan 对索引使用有什么影响?

Postgres 18 引入了 B-tree 跳过扫描(skip scan),允许多列索引在查询条件只命中后列且前导列基数较低时被使用。Postgres 19 延续了这一特性。这意味着对于像 (status, created_at) 这样的索引,当查询只过滤 created_at 时,如果 status 只有少数几个值,索引也能被利用,从而可能减少额外索引的创建。

🏷️

标签

➡️

继续阅读