AI辅助 PolarDB内核学习 - 25 优化器(plan模块) 核心模块 planmain.c
AI辅助 PolarDB内核学习 - 25 优化器(plan模块) 核心模块 planmain.c
以下从多维度对PostgreSQL优化器核心模块planmain.c进行深度解析:
一、架构师视角 - 模块定位与流程
二、内核开发者视角 - 核心代码解析
2.1 主流程(query_planner函数)
2.2 关键数据结构
// 连接消除上下文(analyzejoins.c)
typedefstruct {
List *joinlist; // 原始连接列表
Relids outer_rels; // 外层关系集合
bool removed_any; // 是否执行过删除
} JoinRemovalContext; // 等价类信息(planmain.c)
typedefstruct {
List *ec_members; // 等价成员列表
Relids ec_relids; // 涉及的基表集合
} EquivalenceClass;
三、DBA视角 - 优化器行为特征
3.1 外连接优化示例
EXPLAINSELECT *
FROM A LEFTJOIN B ON A.id=B.aid
WHERE B.x ISNOTNULL;
优化器行为:
remove_useless_joins检测到WHERE条件使LEFT JOIN等价于INNER JOIN重写连接类型为INNER JOIN -- PS: 应该是 B.* is not null? 或 B.x 有not null约束? 优化后的执行计划减少不必要的NULL扩展
3.2 统计信息应用
四、重点算法深度解析
4.1 连接树分解(deconstruct_jointree)
4.2 等价类生成
voidgenerate_base_implied_equalities(PlannerInfo *root){
foreach(ec, root->eq_classes) {
if (ec->ec_has_const) {
// 生成形如A.x = 5的约束
distribute_restrictinfo_to_rels(...);
}
if (ec->ec_broken)
continue;
// 生成跨表等价条件
generate_join_implied_equalities(...);
}
}
典型场景:
WHERE A.x = B.y AND B.y = 10
→ 推导出A.x = 10
五、并行查询处理
5.1 并行度决策逻辑
// planmain.c中并行安全检查
final_rel->consider_parallel =
root->glob->parallelModeOK &&
is_parallel_safe(root, parse->jointree->quals);
影响因素:
基表的parallel_safe标记 表达式中的并行不安全函数 GUC参数force_parallel_mode
5.2 并行执行示例
CREATETABLE t (idint) WITH (parallel_workers = 4);
EXPLAINSELECTCOUNT(*) FROM t;
-- 可能生成并行计划:
Finalize Aggregate
-> Gather
-> Partial Aggregate
-> Parallel Seq Scan
六、扩展机制
6.1 自定义优化规则
通过set_plan_references扩展点:
Plan *set_plan_references(...){
if (plan->type == T_CustomScan) {
// 处理自定义扫描类型
handle_custom_scan_refs(...);
}
// 标准处理流程
return plan;
}
6.2 连接消除扩展
// analyzejoins.c扩展示例
staticbool
custom_join_is_removable(...){
if (custom_check_condition(...))
returntrue;
returnfalse;
}
七、诊断与调优
7.1 执行计划分析要点
EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM A JOIN B ON A.id=B.aid;
关注点:
连接顺序是否最优 连接方法选择(Hash Join vs Merge Join) 内存使用是否合理
7.2 关键GUC参数
-- 优化器行为控制
SET enable_nestloop = off; -- 禁用嵌套循环
SET join_collapse_limit = 8; -- 控制连接重排序
SET from_collapse_limit = 8; -- 控制子查询展开
八、代码演进建议
动态统计信息更新:
// 在build_base_rel_tlists中添加:
if (need_stats_update(rel))
auto_analyze_rel(rel);
机器学习代价预测:
# 在生成路径时调用预测模型
cost = ml_predict_cost(path_features)
通过深入理解planmain.c的实现,开发者可以更好地定制优化规则,DBA能精准识别执行计划瓶颈,架构师可设计更高效的查询模式。建议结合EXPLAIN输出与源码调试器(gdb)观察优化器决策过程。