杨江华:以 PostgreSQL 的货币计价:pg_orca 与 PG 对齐的成本模型
内容提要
pg_orca 为 ORCA 优化器移植了 PostgreSQL 的 costsize.c 成本模型(CCostModelPG),自2026年5月起成为默认模型。它直接读取 PostgreSQL 的 GUC 参数,按算子逐一计算成本,解决了 ORCA 原有 Greenplum 成本模型与 PostgreSQL 单位不一致、忽略 DBA 调参的问题。主要难点在于启动成本、重绑定与循环次数、提前终止三处差异。回归测试用311条 EXPLAIN 校验,要求同形计划成本误差在2%以内,目前188条中已有183条达标。
延伸解读
成本模型对齐的实际意义
pg_orca 的 CCostModelPG 直接读取 PostgreSQL 的 GUC 参数(如 random_page_cost、work_mem),使 ORCA 的成本单位与 PostgreSQL 一致。这意味着 DBA 调整这些参数时,ORCA 的选计划行为会同步变化,EXPLAIN 中的成本数值也可直接对比。当两个优化器选择不同计划时,原因更可能是搜索空间或行数估算差异,而非成本单位不一致,从而降低调试难度。
移植中的三个关键差异
文章指出 ORCA 与 PostgreSQL 在计划描述上有三处根本不同:ORCA 只报告总成本,缺少启动成本,而 LIMIT 需要区分两者;ORCA 用重绑定次数而非循环次数来计价嵌套循环内层,需将重绑定数作为 loop_count 传入;半连接和反连接会提前终止,需按匹配行数折减内层扫描成本。这些差异是移植 costsize.c 的主要难点,处理不当会导致计划选择偏差。
回归测试的校验方式与现状
test/cost_align.sh 对 311 条 EXPLAIN 分别用 PostgreSQL 和 pg_orca(cost_model=pg)运行,要求顶层算子相同时成本误差在 2% 以内。目前 188 条同形计划中 183 条达标,5 条失败;不同计划的 123 条仅列出供检查,不视为失败,因为差异源于 ORCA 更大的搜索空间。这种区分有助于定位真正的成本计算问题。
成本对齐带来的新风险
成本对齐后,ORCA 可能选择以前因成本过高而排除的计划。例如 PostgreSQL 对 CTE Scan 定价很低,ORCA 采用相同价格后开始选择两个 CTE Scan 上的 Merge Join,但 PostgreSQL 的 CTE Scan 无法标记和恢复位置,导致崩溃。修复需在 ORCA 的属性推导中完成,而非成本模型。这说明新成本模型会打开新的搜索空间,测试必须跟进。
Q&A
pg_orca 为什么需要一个新的成本模型?
ORCA 原本使用为 Greenplum MPP 集群校准的成本模型,其常数基于 Greenplum 硬件,在单机 PostgreSQL 上计价单位与 PostgreSQL 不一致,并且忽略 DBA 常用的调参参数(如 random_page_cost、work_mem、effective_cache_size),导致 EXPLAIN 对比时难以理解 ORCA 的选择。因此 pg_orca 引入了移植自 PostgreSQL costsize.c 的 CCostModelPG。
CCostModelPG 是如何与 PostgreSQL 的成本参数保持一致的?
CCostModelPG 不保留自己的成本常数,而是通过 extern "C" 声明 PostgreSQL 的 planner 全局变量,并在计价时实时读取,包括 seq_page_cost、random_page_cost、cpu_tuple_cost、cpu_index_tuple_cost、cpu_operator_cost、effective_cache_size、work_mem、hash_mem_multiplier 等。因此 SET random_page_cost = 1.1 会同时影响 ORCA 和 PostgreSQL 的计划选择。
pg_orca 在移植 costsize.c 时遇到了哪些主要难点?
主要难点有三处:1) PostgreSQL 区分启动成本和总成本,而 ORCA 只报告总成本,LIMIT 等需要启动成本;2) ORCA 使用重绑定次数(rebinds)计价嵌套循环内侧,而 PostgreSQL 使用循环次数(loop_count)并考虑缓存效应;3) 半连接和反连接提前终止时,PostgreSQL 只计算部分内侧扫描成本,ORCA 原先未处理导致成本偏高。
pg_orca 如何验证新成本模型与 PostgreSQL 的一致性?
pg_orca 使用 test/cost_align.sh 运行 311 条 EXPLAIN,分别通过 PostgreSQL 规划器和 ORCA(cost_model = pg)执行。当两者选择相同顶层算子时,要求成本误差在 2% 以内。目前 188 条同形计划中已有 183 条达标,5 条超出误差;不同计划的 123 条被列出供检查,但不视为失败。
成本对齐后,ORCA 的计划选择发生了什么变化?
成本对齐后,ORCA 开始选择之前被 Greenplum 校准排除的计划。例如,PostgreSQL 对 CTE Scan 计价很低,ORCA 采用相同价格后选择了两个 CTE Scan 的 Merge Join,但 PostgreSQL 的 CTE Scan 无法标记和恢复位置,导致计划崩溃。修复需要在 ORCA 的属性推导中处理,而非成本模型本身。
使用 pg_orca 的 PG 对齐成本模型对用户有什么实际好处?
当两个规划器以相同方式计价时,pg_orca 的 EXPLAIN 输出与 PostgreSQL 的 EXPLAIN 含义一致,成本值可直接比较,DBA 的调参经验也能延续。如果 ORCA 仍选择不同计划,原因在于搜索空间或行估计不同,而非计价单位差异,这使得计划调试更加容易。