我的编程空间,编程开发者的网络收藏夹
学习永远不晚

PostgreSQL中如何生成子链接执行计划、使用Param替换上层Vars以及转换表达式为隐式AND格式

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

PostgreSQL中如何生成子链接执行计划、使用Param替换上层Vars以及转换表达式为隐式AND格式

这篇文章主要为大家展示了“PostgreSQL中如何生成子链接执行计划、使用Param替换上层Vars以及转换表达式为隐式AND格式”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“PostgreSQL中如何生成子链接执行计划、使用Param替换上层Vars以及转换表达式为隐式AND格式”这篇文章吧。

一、主函数

主函数preprocess_expression先前章节也介绍过,在此函数中调用了生成子链接执行计划、使用Param替换上层Vars以及转换表达式为隐式AND格式(implicit-AND format)等相关子函数。
preprocess_expression

 
 static Node *
 preprocess_expression(PlannerInfo *root, Node *expr, int kind)
 {
     //...
 
     
     if (root->parse->hasSubLinks)//扩展子链接为子计划
         expr = SS_process_sublinks(root, expr, (kind == EXPRKIND_QUAL));
 
     
 
     
     if (root->query_level > 1)
         expr = SS_replace_correlation_vars(root, expr);//使用Param节点替换上层的Vars
 
     
     if (kind == EXPRKIND_QUAL)//转换为隐式AND格式
         expr = (Node *) make_ands_implicit((Expr *) expr);
 
     return expr;
 }

二、生成子链接执行计划

先前的章节已介绍了上拉子链接的相关处理过程,对于不能上拉的子链接,PG会生成子执行计划.对于会生成常量的子链接,则会把生成的常量记录在Param中,在需要的时候由父查询使用.
例1:以下的子链接,PG会生成子计划,并把子链接的结果物化(Materialize)提升整体性能.

testdb=# explain verbose select * from t_dwxx where dwbh > all (select b.dwbh from t_grxx b);
                                   QUERY PLAN                                    
---------------------------------------------------------------------------------
 Seq Scan on public.t_dwxx  (cost=0.00..1498.00 rows=80 width=474)
   Output: t_dwxx.dwmc, t_dwxx.dwbh, t_dwxx.dwdz
   Filter: (SubPlan 1)
   SubPlan 1
     ->  Materialize  (cost=0.00..17.35 rows=490 width=38)
           Output: b.dwbh
           ->  Seq Scan on public.t_grxx b  (cost=0.00..14.90 rows=490 width=38)
                 Output: b.dwbh
(8 rows)

例2:以下的子链接,PG会把生成的常量记录在Param中(注意生成的参数:$0)

testdb=# explain verbose select * from t_dwxx a where exists (select  max(b.dwbh) from t_grxx b);
                                   QUERY PLAN                                    
---------------------------------------------------------------------------------
 Result  (cost=16.14..27.73 rows=160 width=474)
   Output: a.dwmc, a.dwbh, a.dwdz
   One-Time Filter: $0
   InitPlan 1 (returns $0)
     ->  Aggregate  (cost=16.12..16.14 rows=1 width=32)
           Output: max((b.dwbh)::text)
           ->  Seq Scan on public.t_grxx b  (cost=0.00..14.90 rows=490 width=38)
                 Output: b.dwbh, b.grbh, b.xm, b.nl
   ->  Seq Scan on public.t_dwxx a  (cost=16.14..27.73 rows=160 width=474)
         Output: a.dwmc, a.dwbh, a.dwdz
(10 rows)

源代码如下:
SS_process_sublinks


 Node *
 SS_process_sublinks(PlannerInfo *root, Node *expr, bool isQual)
 {
     process_sublinks_context context;
 
     context.root = root;
     context.isTopQual = isQual;
     return process_sublinks_mutator(expr, &context);//调用XX_mutator函数遍历并处理
 }
 
 static Node *
 process_sublinks_mutator(Node *node, process_sublinks_context *context)
 {
     process_sublinks_context locContext;
 
     locContext.root = context->root;
 
     if (node == NULL)
         return NULL;
     if (IsA(node, SubLink))//子链接
     {
         SubLink    *sublink = (SubLink *) node;
         Node       *testexpr;
 
         
         locContext.isTopQual = false;
         testexpr = process_sublinks_mutator(sublink->testexpr, &locContext);
 
         
         return make_subplan(context->root,
                             (Query *) sublink->subselect,
                             sublink->subLinkType,
                             sublink->subLinkId,
                             testexpr,
                             context->isTopQual);//生成子执行计划,与整体的执行计划类似
     }
 
     
     if (IsA(node, PlaceHolderVar))
     {
         if (((PlaceHolderVar *) node)->phlevelsup > 0)
             return node;
     }
     else if (IsA(node, Aggref))
     {
         if (((Aggref *) node)->agglevelsup > 0)
             return node;
     }
 
     
     Assert(!IsA(node, SubPlan));
     Assert(!IsA(node, AlternativeSubPlan));
     Assert(!IsA(node, Query));
 
     
     if (and_clause(node))//AND语句
     {
         List       *newargs = NIL;
         ListCell   *l;
 
         
         locContext.isTopQual = context->isTopQual;
 
         foreach(l, ((BoolExpr *) node)->args)
         {
             Node       *newarg;
 
             newarg = process_sublinks_mutator(lfirst(l), &locContext);
             if (and_clause(newarg))
                 newargs = list_concat(newargs, ((BoolExpr *) newarg)->args);
             else
                 newargs = lappend(newargs, newarg);
         }
         return (Node *) make_andclause(newargs);
     }
 
     if (or_clause(node))//OR语句
     {
         List       *newargs = NIL;
         ListCell   *l;
 
         
         locContext.isTopQual = context->isTopQual;
 
         foreach(l, ((BoolExpr *) node)->args)
         {
             Node       *newarg;
 
             newarg = process_sublinks_mutator(lfirst(l), &locContext);
             if (or_clause(newarg))
                 newargs = list_concat(newargs, ((BoolExpr *) newarg)->args);
             else
                 newargs = lappend(newargs, newarg);
         }
         return (Node *) make_orclause(newargs);
     }
 
     
     locContext.isTopQual = false;
 
     return expression_tree_mutator(node,
                                    process_sublinks_mutator,
                                    (void *) &locContext);
 }

三、使用Param替换上层变量

SQL例子参考"二、生成子链接执行计划"中的例2,这也是使用Param替代Var的一个例子.
源代码如下:

 
 Node *
 SS_replace_correlation_vars(PlannerInfo *root, Node *expr)
 {
     
     //调用XX_mutator遍历处理
     return replace_correlation_vars_mutator(expr, root);
 }
 
 static Node *
 replace_correlation_vars_mutator(Node *node, PlannerInfo *root)
 {
     if (node == NULL)
         return NULL;
     if (IsA(node, Var))//Var
     {
         if (((Var *) node)->varlevelsup > 0)
             return (Node *) replace_outer_var(root, (Var *) node);//使用Param替换
     }
     if (IsA(node, PlaceHolderVar))
     {
         if (((PlaceHolderVar *) node)->phlevelsup > 0)
             return (Node *) replace_outer_placeholdervar(root,
                                                          (PlaceHolderVar *) node);
     }
     if (IsA(node, Aggref))
     {
         if (((Aggref *) node)->agglevelsup > 0)
             return (Node *) replace_outer_agg(root, (Aggref *) node);
     }
     if (IsA(node, GroupingFunc))
     {
         if (((GroupingFunc *) node)->agglevelsup > 0)
             return (Node *) replace_outer_grouping(root, (GroupingFunc *) node);
     }
     return expression_tree_mutator(node,
                                    replace_correlation_vars_mutator,
                                    (void *) root);
 }

 
 static Param *
 replace_outer_var(PlannerInfo *root, Var *var)//构造Param替换Var
 {
     Param      *retval;
     int         i;
 
     Assert(var->varlevelsup > 0 && var->varlevelsup < root->query_level);
 
     
     i = assign_param_for_var(root, var);
 
     retval = makeNode(Param);
     retval->paramkind = PARAM_EXEC;
     retval->paramid = i;
     retval->paramtype = var->vartype;
     retval->paramtypmod = var->vartypmod;
     retval->paramcollid = var->varcollid;
     retval->location = var->location;
 
     return retval;
 }

四、转换表达式为隐式AND格式

源码如下:

 List *
 make_ands_implicit(Expr *clause)
 {
     
     if (clause == NULL)//如为NULL,返回空指针
         return NIL;             
     else if (and_clause((Node *) clause))//AND语句,直接返回AND中的args参数
         return ((BoolExpr *) clause)->args;
     else if (IsA(clause, Const) &&
              !((Const *) clause)->constisnull &&
              DatumGetBool(((Const *) clause)->constvalue))
         return NIL;             
     else
         return list_make1(clause);//返回List
 }

以上是“PostgreSQL中如何生成子链接执行计划、使用Param替换上层Vars以及转换表达式为隐式AND格式”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

PostgreSQL中如何生成子链接执行计划、使用Param替换上层Vars以及转换表达式为隐式AND格式

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

目录