PostgreSQL查询优化器源码分析--整体流程

函数间关系的主要逻辑如下:

planner(){――第(1)层

  standard_planner(){――第(2)层 

subquery_planner(){――第(3)层

  pull_up_sublinks(); //上拉子链接

pull_up_subqueries(); //上拉子查询

preprocess_expression(); //标准化表达式:把WHERE子句内容“标准化”为便于使用的形式,包括拉平AND/OR;找出子句中OR不同分支下重复的谓词。如果约束条件有子链接子查询,则递归调用subquery_planner()处理子链接子查询

reduce_outer_joins(); //消除外连接

//以上部分的代码,主要完成逻辑优化的工作

grouping_planner(){――第(4)层 //生成查询计划

query_planner(){――第(5)层

make_one_rel(){――第(6)层//生成新关系

               set_base_rel_pathlist(): //找出所有访问基表的方法,包括顺序扫描和索引扫描

make_rel_from_joinlist (){――第(7)层

//决定使用什么查询优化的算法(遗传算法还是动态规划还是用户自定义的算法)生成一棵查询树的所有访问路径,得到最优的路径

                 //如果定义的遗传算法的连接顺序选择,那么采用它;否则,如下

                 standard_join_search (){――第(8)层 //实现动态规划算法,为一个查询找出所有可能的连接路径

join_search_one_level () {――第(9)层 //89层是实现动态规划算法

  make_join_rel () {――第(10)层 //查找或创建一个RelOptInfo节点,用于表示2个关系的连接结果,把2个关系的连接路径加入这个RelOptInfo节点

    build_join_rel() {――第(11)层

      Find or build the join RelOptInfo

    Consider paths using each rel as both outer and inner //尝试把每个关系作为外关系、作为内关系(一个关系作为一次连接的内关系或外关系对效率有影响)

  }――第(11)层结束,build_join_rel()

  }――第(10)层结束,make_join_rel ()

  make_rels_by_clause_joins(); //会调用make_join_rel ()

  make_rels_by_clauseless_joins();//会调用make_join_rel ()

}――第(9)层结束,join_search_one_level ()               

                         set_cheapest(rel); //被循环调用,得到每一个关系上的花费最低的路径

}――第(8)层结束,standard_join_search ()

               }――第(7)层结束,make_rel_from_joinlist ()

                }――第(6)层结束,make_one_rel()

}――第(5)层结束,query_planner() //返回值是void,但参数中有2个参数(cheapest_path, sorted_path)返回和最优的查询计划路径

optimize_minmax_aggregates(); //minmax聚集计划优化

create_plan(); //工具求解得到的最优路径,创建(初步的)查询计划

//添加相应的计划节点(包括agggroupdistinctsortlimit),生成完整的查询计划

      }――第(4)层结束,grouping_planner()

}――第(3)层结束,subquery_planner()

set_plan_references(); //一些清理辅助工作

}――第(2)层结束,standard_planner()

}――第(1)层结束,planner()

 

以上是查询优化的整体流程,在进入第6层之前是的逻辑查询计划生成,如子查询的消除等逻辑优化策略都是在这个阶段之前完成的。

6层之后是物理查询计划生成,利用动态规划(dynamic programming)的算法,实现多个关系的访问方式确定(顺序访问、索引访问、TID访问)、连接方式确定(嵌套循环连接算法、归并连接算法、hash连接算法)、连接顺序选取(左深树、右深树、紧密树)。

对于连接顺序,PG解释如下(可留心红色字体标明的决定连接顺序的方法的特点):

We consider left-handed plans (the outer rel of an upper join is a joinrel,

but the inner is always a single list item); right-handed plans (outer rel

is always a single item); and bushy plans (both inner and outer can be

joins themselves).  For example, when building {1 2 3 4} we consider

joining {1 2 3} to {4} (left-handed), {4} to {1 2 3} (right-handed), and

{1 2} to {3 4} (bushy), among other choices.

 

生成join关系的同时,把可用的生成路径都添加到每个关系(包括基表和连接生成的表)的pathlist中,每个path除了表示连接的方法,还包含各方面(启动代价,总的执行代价,含某种顺序的代价,unique的代价等)代价估计的结果。当所有的有用的路径被添加之后,通过代价的比较,选出代价最小的最佳路径作为上层选取的贪婪的依据,每层都如此处理,直至顶层时,最佳查询路径被选取出来,这是一个唯一的结果表,至此,基于代价的查询优化完成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值