Pavel Luzanov:PostgreSQL 19:第 5.1 部分(查询规划工具)或 2026-03 CommitFest

Pavel Luzanov:PostgreSQL 19:第 5.1 部分(查询规划工具)或 2026-03 CommitFest

💡 原文英文,约3000词,阅读约需11分钟。
📝

内容提要

PostgreSQL 19 查询优化新特性:新增 pg_plan_advice 扩展,可记录并回放计划器决策以稳定执行计划;pg_stash_advice 支持按查询标识自动应用建议。EXPLAIN 计时改用 TSC 寄存器降低开销。优化器可将非空列的 IS NOT DISTINCT FROM 转为等值连接,NOT IN 子查询在无 NULL 时可用反连接,虚拟生成列可建扩展统计,postgres_fdw 支持导入远程统计,JIT 默认关闭。

🔎

延伸解读

计划建议的持久化与自动应用

pg_plan_advice 和 pg_stash_advice 扩展配合使用,可记录并回放计划器决策以稳定执行计划。pg_stash_advice 将查询标识符映射到建议字符串,并可通过参数自动应用。建议存储在内存中,但通过 shared_preload_libraries 加载后,后台工作进程会定期将建议保存到文件,重启后自动恢复。这为生产环境提供了无需修改应用代码即可固定计划的能力。

EXPLAIN 计时开销的降低

PostgreSQL 19 中,EXPLAIN 的 analyze 和 timing 选项默认使用 CPU 的 TSC 寄存器进行计时,替代了 clock_gettime 系统调用,从而减少性能分析开销。但 TSC 频率在虚拟机和 hypervisor 上可能不可靠,因此新增 timing_clock_source 参数允许手动选择时钟源。用户可通过 pg_test_timing 工具检查推荐设置。

优化器对 NULL 语义的利用

优化器现在能利用列的非空约束来生成更优计划。例如,当 IS NOT DISTINCT FROM 两侧均为 NOT NULL 列时,可转换为等值连接;NOT IN 子查询在无 NULL 时可用反连接;LEFT JOIN 后对非连接列的非空检查也可转为反连接。这些转换避免了昂贵的逐行过滤,显著提升查询性能。

统计信息与 JIT 的默认变更

虚拟生成列现在可直接创建扩展统计信息,无需在表达式上定义,提高了基数估计准确性。postgres_fdw 新增 import_stats 选项,允许从远程表复制统计信息,但需用户自行维护远程统计的时效性。此外,JIT 编译默认关闭,因为对 OLTP 短查询收益有限,关闭可避免计划信息杂乱。

❓

Q&A

PostgreSQL 19 中 pg_plan_advice 扩展的主要作用是什么?

pg_plan_advice 扩展用于稳定查询执行计划。它可以记录规划器在生成计划时做出的关键决策,并允许用户将这些决策作为建议反馈给规划器,从而锁定执行计划,避免后续执行时计划发生变化。

如何使用 pg_stash_advice 自动为不同查询应用计划建议?

首先创建扩展并加载模块,然后使用 pg_create_advice_stash 创建建议存储,通过 pg_set_stashed_advice 将查询标识符与建议字符串关联。最后设置 pg_stash_advice.stash_name 参数(可在会话、数据库或角色级别),规划器便会自动查找并应用对应建议。

PostgreSQL 19 在 EXPLAIN 计时方面做了哪些改进?

EXPLAIN 的 analyze 和 timing 选项现在可以通过读取 CPU 的 TSC 寄存器(rdtsc)来测量执行时间,替代了之前的 clock_gettime 系统调用,从而降低了性能分析的开销。同时新增 timing_clock_source 参数,允许手动选择时钟源。

PostgreSQL 19 如何优化 NOT IN 子查询的执行计划?

当 NOT IN 子查询涉及的列被保证不含 NULL 值时,规划器现在可以考虑使用反连接(anti-join)计划,例如 Hash Right Anti Join,从而大幅提升查询性能。此前由于可能存在的 NULL 值,规划器无法使用反连接,导致执行计划不佳。

PostgreSQL 19 对虚拟生成列的统计信息收集有何改进?

现在可以直接在虚拟生成列上创建扩展统计信息,只需指定列名即可,无需再针对生成表达式创建。这提高了基数估计的准确性,避免了因统计信息缺失导致的错误估算。

PostgreSQL 19 中 postgres_fdw 的 import_stats 选项有什么作用?

import_stats 选项允许在对远程外部表执行 ANALYZE 时,直接复制远程表已有的统计信息(pg_stats)到本地,而不是重新采样。这有助于提高查询计划的准确性,但需要用户自行确保远程统计信息是最新的。

🏷️

标签

➡️

继续阅读