PostgreSQL查询代价估算(六)

来源:互联网 发布:有线电视有网络吗 编辑:程序博客网 时间:2024/06/03 21:14

1.1.1.1     哈希连接代价:final_cost_hashjoin

函数功能:

计算两个关系使用hash连接算法的花费。内外表的元组数和Hash运算的选择率乘积得到了参与hash连接的元组数,这个hash连接的元组数和hash创建的花费决定了CPU的花费。

对于hashjoin花费的计算,分为两个函数:

1.        一是initial_cost_hashjoin函数,初步估计hashjoin算法的花费,形成的结果会作为final_cost_hashjoin的入口参数(JoinCostWorkspace *workspace)传入final_cost_hashjoin函数;

2.        二是final_cost_hashjoin函数,对hashjoin算法的花费进行全面的估计(如:CPU/IO的花费、内表是否唯一、不同连接类型的差别等)。

 

代码分析:

void

final_cost_hashjoin(PlannerInfo *root, HashPath *path,

                                   JoinCostWorkspace*workspace,

                                   SpecialJoinInfo*sjinfo,

                                   SemiAntiJoinFactors*semifactors)

{......

       virtualbuckets= (double) numbuckets *(double) numbatches;

      

    //hash算法,首先为内表构造hash链表,外表的连接的对象,根据hash函数计算值向内表形成的hash链表上映射;所以,需要求解构造hash的花费,即求解构造内表所在的hash的花费

 

       //如果唯一,则没有重复的,平均分布即可,所以每个bucket的概率是相同的

       if(IsA(inner_path, UniquePath))

              innerbucketsize= 1.0 / virtualbuckets;

       else

       {

              innerbucketsize= 1.0;

              foreach(hcl,hashclauses)//遍历每条hash子句(参数传入的限制条件)

              {......

                     //hash子句被内表涵盖

                     if(bms_is_subset(restrictinfo->right_relids,inner_path->parent->relids))

                     {

                            thisbucketsize= restrictinfo->right_bucketsize;

                            if(thisbucketsize < 0)//如果小于零,则缓存中不存在,需要重新计算

                            {

                                   thisbucketsize= estimate_hash_bucketsize(root,

                                                               get_rightop(restrictinfo->clause),virtualbuckets);

                                   restrictinfo->right_bucketsize= thisbucketsize;

                            }

                     }

                     else//否则,hash子句被外表涵盖;处理过程类似if语句

                     {......}

 

                     if(innerbucketsize > thisbucketsize)//保存最小值

                            innerbucketsize= thisbucketsize;

              }

       }

 

       //计算限制等类型的条件的CPU花费

       cost_qual_eval(&hash_qual_cost,hashclauses, root);

       cost_qual_eval(&qp_qual_cost,path->jpath.joinrestrictinfo, root);

......

  //如果是半连接或反半连接,注意:

  //1 半连接或反半连接语义,找到一个满足连接条件的,即可停止对同类型的进行扫描,所以不用匹配很多元组,所以花费应该少

  //2 不管是何种方式,计算花费的主要因子通常都是在元组数、匹配度上,所以如下计算都有这样的考虑

       if(path->jpath.jointype == JOIN_SEMI || path->jpath.jointype == JOIN_ANTI)

       {......

              //只要有一个匹配,就可以停止扫描其他同类项

              outer_matched_rows= rint(outer_path_rows * semifactors->outer_match_frac);

              inner_scan_frac= 2.0 / (semifactors->match_count + 1.0);

 

              startup_cost+= hash_qual_cost.startup;

              run_cost+= hash_qual_cost.per_tuple * outer_matched_rows *

                     clamp_row_est(inner_path_rows* innerbucketsize * inner_scan_frac) * 0.5;

 

              //为不匹配的情况,计算花费

              run_cost+= hash_qual_cost.per_tuple *

                     (outer_path_rows- outer_matched_rows) *

                     clamp_row_est(inner_path_rows/ virtualbuckets) * 0.05;

 

              if(path->jpath.jointype == JOIN_SEMI)

                     hashjointuples= outer_matched_rows;

              else

                     hashjointuples= outer_path_rows - outer_matched_rows;

       }

       else//普通的连接类型,认为约有0.5的匹配度(这算是一种启发式规则)

       {

              startup_cost+= hash_qual_cost.startup;

              run_cost+= hash_qual_cost.per_tuple * outer_path_rows *

                     clamp_row_est(inner_path_rows* innerbucketsize) * 0.5;

 

              hashjointuples= approx_tuple_count(root, &path->jpath, hashclauses);

       }

 

       //计算CPU花费

       startup_cost+= qp_qual_cost.startup;

       cpu_per_tuple= cpu_tuple_cost + qp_qual_cost.per_tuple;

       run_cost+= cpu_per_tuple * hashjointuples;

 

       path->jpath.path.startup_cost= startup_cost;

       path->jpath.path.total_cost= startup_cost + run_cost;

}

 

调用关系图解:

PostgreSQL查询代价估算(六) - 那海蓝蓝 - 那海蓝蓝的博客
 


final_cost_hashjoin函数被create_hashjoin_path函数调用,直至被add_paths_to_joinrel函数调用,完成两表连接的hashjoin连接算法的花费估算。
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孩子好几天不大便怎么办 宝宝7天没有大便怎么办 40天小孩不拉屎怎么办 40多天婴儿便秘怎么办 小孩拉绿色稀便怎么办 5岁好几天不拉屎怎么办 2个月宝宝不大便怎么办 两月宝宝不拉屎怎么办 好几天没大便了怎么办 初生婴儿便秘解不出大便怎么办 小孩大便拉不出来怎么办 新生儿3天没大便怎么办 新生儿5天没大便怎么办 小孩好几天不大便怎么办 婴儿10天不拉屎怎么办 3岁大便拉不出来怎么办 孩子大便拉不出来怎么办 4岁大便拉不出来怎么办 排位队友太坑怎么办 lol遇到坑b队友怎么办 被冷暴力分手后怎么办 孕早期半夜饿了怎么办 怀孕了月经还来怎么办 大米生虫子吃了怎么办 老公有外遇不回家怎么办 老公和小三有了孩子怎么办 祖坟给人挖了怎么办 妯娌关系和不来怎么办 婆婆老说我不好怎么办 婆婆对我妈不好怎么办 老公嫌老婆胸小怎么办 牙上颚的肉肿了怎么办 乐视手机音量小怎么办 手表日期调过了怎么办 机械表日期不走怎么办 差银行钱还不起怎么办 有人威胁要杀我怎么办 受人威胁要打我怎么办 胳膊起疙瘩很痒怎么办 后背长很多痘痘怎么办 肩膀两边长痘痘怎么办