执行计划提示
Apache Cloudberry 使用两种查询优化器:基于 Postgres 的优化器和 GPORCA。每种优化器都针对特定类型的工作负载进行了优化:
- 基于 Postgres 的优化器:适用于事务型工作负载。
- GPORCA:适用于分析型和混合事务-分析型工作负载。
在处理查询时,优化器会遍历大量等价执行计划的搜索空间,并根据表统计信息和基数估算模型预测每个操作处理的行数。优化器使用成本模型为每个计划分配一个成本值,并选择成 本最低的计划作为最终执行计划。
执行计划提示是用户提供给优化器的指令,用于影响查询的执行策略。通过提示,用户可以覆盖优化器的默认行为,从而应对以下问题:行数估算不准确、扫描方式不理想、连接类型选择不当或连接顺序低效。本文将介绍执行计划提示的不同类型及其适用场景。
提示
Apache Cloudberry 当前不支持控制 Motion 算子的提示。
快速示例
提示
要启用执行计划提示功能,必须先在 psql 会话中加载相关模块:
LOAD 'pg_hint_plan';
也可以在数据库级别或用户级别配置自动加载:
ALTER DATABASE a_database SET session_preload_libraries='pg_hint_plan';
ALTER USER a_user SET session_preload_libraries='pg_hint_plan';
CREATE TABLE foo(a int);
CREATE INDEX ON foo(a);
INSERT INTO foo SELECT i FROM generate_series(1, 100000)i;
LOAD 'pg_hint_plan';
SHOW pg_hint_plan.enable_hint;
pg_hint_plan.enable_hint
--------------------------
on
(1 row)
EXPLAIN SELECT count(*) FROM foo WHERE a > 6;
QUERY PLAN
--------------------------------------------------------------------------------------
Finalize Aggregate (cost=537.05..537.06 rows=1 width=8)
-> Gather Motion 3:1 (slice1; segments: 3) (cost=536.99..537.04 rows=3 width=8)
-> Partial Aggregate (cost=536.99..537.00 rows=1 width=8)
-> Seq Scan on foo (cost=0.00..453.67 rows=33330 width=0)
Filter: (a > 6)
Optimizer: Postgres-based planner
(6 rows)
/*+ IndexScan(foo foo_a_idx) */
EXPLAIN SELECT count(*) FROM foo WHERE a > 6;
QUERY PLAN
---------------------------------------------------------------------------------------------
Finalize Aggregate (cost=809.00..809.01 rows=1 width=8)
-> Gather Motion 3:1 (slice1; segments: 3) (cost=808.94..808.99 rows=3 width=8)
-> Partial Aggregate (cost=808.94..808.95 rows=1 width=8)
-> Index Scan using foo_a_idx on foo (cost=0.17..725.61 rows=33330 width=0)
Index Cond: (a > 6)
Optimizer: Postgres-based planner
(6 rows)
也可以同时指定多个提示,例如控制扫描方式和行数估计:
/*+ IndexScan(t1 my_index) Rows(t1 t2 #1000) */
SELECT * FROM t1 JOIN t2 ON t1.a = t2.a WHERE t1.a < 100;
基数提示(Cardinality Hints)
当优化器对连接操作的行数估算不准确时,可能会选择效率较差的计划,例如使用 Broadcast 而非 Redistribute,或错误地偏好 Merge Join 而非 Hash Join。基数提示可用于调整特定操作的行数估计值,尤其适用于统计信息缺失或已过期的情况。
示例:
/*+ Rows(t1 t2 t3 #42) */ SELECT * FROM t1, t2, t3; -- 设置估计行为 42
/*+ Rows(t1 t2 t3 +42) */ SELECT * FROM t1, t2, t3; -- 原估计值增加 42
/*+ Rows(t1 t2 t3 -42) */ SELECT * FROM t1, t2, t3; -- 原估计值减少 42
/*+ Rows(t1 t2 t3 *42) */ SELECT * FROM t1, t2, t3; -- 原估计值乘以 42
提示
基数提示目前仅在 ORCA 优化器中生效,Postgres 优化器不会识别此类提示。