AI辅助 PolarDB内核学习 - 24 优化器(plan模块) 入口代码 planner.c
AI辅助 PolarDB内核学习 - 24 优化器(plan模块) 入口代码 planner.c
以下从多维度对PostgreSQL查询优化器核心模块planner.c进行深度解析:
一、架构师视角 - 模块架构设计
二、内核开发者视角 - 关键代码结构
2.1 核心数据结构
// 分组集数据(处理GROUPING SETS)
typedefstruct {
List *rollups; // 多层分组集合
double dNumHashGroups; // 哈希分组估算数
Bitmapset *unhashable_refs;// 不可哈希列
} grouping_sets_data; // 窗口函数处理上下文
typedefstruct {
WindowClause *wc; // 窗口子句
List *uniqueOrder; // 唯一排序键
} WindowClauseSortData;
2.2 主流程(grouping_planner函数)
三、DBA视角 - 优化器行为特征
3.1 LIMIT优化示例
EXPLAINSELECT * FROM orders ORDERBY order_date LIMIT100;
优化器行为:
preprocess_limit计算有效元组比例优先选择带排序的索引扫描 当 order_date有索引时,使用IndexScan+Limit无索引时采用 Sort+SeqScan
3.2 分组优化策略
SELECT customer_id, SUM(amount)
FROM orders
GROUPBY customer_id
HAVINGSUM(amount) > 1000;
优化器决策点:
使用哈希聚合还是排序聚合 HAVING条件下推时机 分组列基数估算( dNumHashGroups)
四、关键算法深度解析
4.1 分组路径生成(create_ordinary_grouping_paths)
4.2 窗口函数优化(create_one_window_path)
// 窗口函数处理核心逻辑
staticvoidcreate_one_window_path(...){
// 步骤1:确定窗口排序键
get_windowclause_sort_order(...);
// 步骤2:生成排序路径
if (window_has_unique_sort)
pathkeys = NIL; // 无需额外排序
else
add_sort_node(...);
// 步骤3:添加窗口聚合节点
create_windowagg_path(...);
}
典型优化场景:
当窗口函数使用 UNIQUE排序键时,跳过显式排序多个窗口函数共享相同 PARTITION BY时合并计算
五、并行查询处理
5.1 并行度决策
intplan_create_index_workers(Oid tableOid, Oid indexOid){
// 基于表大小和配置参数计算
workers = Min(max_parallel_maintenance_workers,
log2(rel_pages / 1000));
return workers;
}
5.2 并行聚合优化
-- 原始执行计划
Finalize GroupAggregate
-> Gather Merge
-> Partial HashAggregate
-- 优化条件:
1. can_partial_agg()返回true
2. 聚合函数支持并行(标记PARALLEL_SAFE)
3. 无ORDERBY或GROUPINGSETS
六、扩展机制
6.1 优化器钩子
// 插件可注入的钩子函数
typedef PlannedStmt *(*planner_hook_type) (Query *parse,...);
extern PGDLLIMPORT planner_hook_type planner_hook;
// 示例:修改查询树
static PlannedStmt *my_planner(...){
if (parse->commandType == CMD_SELECT)
add_dummy_where_clause(parse); // 注入自定义条件
return standard_planner(...);
}
6.2 自定义扫描提供程序
通过planner.c中的preprocess_expression实现:
Node *preprocess_expression(...){
if (is_custom_scan_expr(expr))
rewrite_custom_scan_expr(...);
// 标准处理流程
return expr;
}
七、诊断与调优
7.1 常见问题模式
pg_stats统计信息 | ||
EXPLAIN ANALYZE的峰值内存 |
7.2 性能调优参数
-- 关键配置示例
SET random_page_cost = 1.1; -- SSD优化
SET work_mem = '64MB'; -- 提升排序/哈希性能
SET parallel_setup_cost = 10; -- 降低并行启动阈值
SET enable_sort = off; -- 强制使用哈希聚合
通过深入理解planner.c的实现机制,开发者可定制优化策略,DBA能精准诊断执行计划问题,架构师可设计更高效的数据库应用模式。建议结合EXPLAIN (ANALYZE, VERBOSE)输出与源码实现进行对比分析。