博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PostgreSQL在何处处理 sql查询之四十九
阅读量:7048 次
发布时间:2019-06-28

本文共 8013 字,大约阅读时间需要 26 分钟。

接前面,继续对 subquery_planner来分析:

下面这一段都是对 表达式进行处理的,对我的简单查询,可以忽略。

/*     * Do expression preprocessing on targetlist and quals, as well as other     * random expressions in the querytree.  Note that we do not need to     * handle sort/group expressions explicitly, because they are actually     * part of the targetlist.     */    parse->targetList = (List *)        preprocess_expression(root, (Node *) parse->targetList,                              EXPRKIND_TARGET);    parse->returningList = (List *)        preprocess_expression(root, (Node *) parse->returningList,                              EXPRKIND_TARGET);    preprocess_qual_conditions(root, (Node *) parse->jointree);    parse->havingQual = preprocess_expression(root, parse->havingQual,                                              EXPRKIND_QUAL);    foreach(l, parse->windowClause)    {        WindowClause *wc = (WindowClause *) lfirst(l);        /* partitionClause/orderClause are sort/group expressions */        wc->startOffset = preprocess_expression(root, wc->startOffset,                                                EXPRKIND_LIMIT);        wc->endOffset = preprocess_expression(root, wc->endOffset,                                              EXPRKIND_LIMIT);    }    parse->limitOffset = preprocess_expression(root, parse->limitOffset,                                               EXPRKIND_LIMIT);    parse->limitCount = preprocess_expression(root, parse->limitCount,                                              EXPRKIND_LIMIT);    root->append_rel_list = (List *)        preprocess_expression(root, (Node *) root->append_rel_list,                              EXPRKIND_APPINFO);    /* Also need to preprocess expressions for function and values RTEs */    foreach(l, parse->rtable)    {        RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);        if (rte->rtekind == RTE_FUNCTION)            rte->funcexpr = preprocess_expression(root, rte->funcexpr,                                                  EXPRKIND_RTFUNC);        else if (rte->rtekind == RTE_VALUES)            rte->values_lists = (List *)                preprocess_expression(root, (Node *) rte->values_lists,                                      EXPRKIND_VALUES);    }

接着继续,是对HAVING 的处理、对我的简单查询而言,也是可以忽略的。

/*     * In some cases we may want to transfer a HAVING clause into WHERE. We     * cannot do so if the HAVING clause contains aggregates (obviously) or     * volatile functions (since a HAVING clause is supposed to be executed     * only once per group).  Also, it may be that the clause is so expensive     * to execute that we're better off doing it only once per group, despite     * the loss of selectivity.  This is hard to estimate short of doing the     * entire planning process twice, so we use a heuristic: clauses     * containing subplans are left in HAVING.    Otherwise, we move or copy the     * HAVING clause into WHERE, in hopes of eliminating tuples before     * aggregation instead of after.     *     * If the query has explicit grouping then we can simply move such a     * clause into WHERE; any group that fails the clause will not be in the     * output because none of its tuples will reach the grouping or     * aggregation stage.  Otherwise we must have a degenerate (variable-free)     * HAVING clause, which we put in WHERE so that query_planner() can use it     * in a gating Result node, but also keep in HAVING to ensure that we     * don't emit a bogus aggregated row. (This could be done better, but it     * seems not worth optimizing.)     *     * Note that both havingQual and parse->jointree->quals are in     * implicitly-ANDed-list form at this point, even though they are declared     * as Node *.     */    newHaving = NIL;    foreach(l, (List *) parse->havingQual)    {        Node       *havingclause = (Node *) lfirst(l);        if (contain_agg_clause(havingclause) ||            contain_volatile_functions(havingclause) ||            contain_subplans(havingclause))        {            /* keep it in HAVING */            newHaving = lappend(newHaving, havingclause);        }        else if (parse->groupClause)        {            /* move it to WHERE */            parse->jointree->quals = (Node *)                lappend((List *) parse->jointree->quals, havingclause);        }        else        {            /* put a copy in WHERE, keep it in HAVING */            parse->jointree->quals = (Node *)                lappend((List *) parse->jointree->quals,                        copyObject(havingclause));            newHaving = lappend(newHaving, havingclause);        }    }    parse->havingQual = (Node *) newHaving;

 接下来的一段,因为我的简单查询没有outer join,所以也可以无视。

/*     * If we have any outer joins, try to reduce them to plain inner joins.     * This step is most easily done after we've done expression     * preprocessing.     */    if (hasOuterJoins)        reduce_outer_joins(root);

紧接着,关键的地方就来了:这里叫作 main planning。

/*     * Do the main planning.  If we have an inherited target relation, that     * needs special processing, else go straight to grouping_planner.     */    if (parse->resultRelation &&        rt_fetch(parse->resultRelation, parse->rtable)->inh)        plan = inheritance_planner(root);    else    {        plan = grouping_planner(root, tuple_fraction);        /* If it's not SELECT, we need a ModifyTable node */        if (parse->commandType != CMD_SELECT)        {            List       *returningLists;            List       *rowMarks;            /*             * Set up the RETURNING list-of-lists, if needed.             */            if (parse->returningList)                returningLists = list_make1(parse->returningList);            else                returningLists = NIL;            /*             * If there was a FOR UPDATE/SHARE clause, the LockRows node will             * have dealt with fetching non-locked marked rows, else we need             * to have ModifyTable do that.             */            if (parse->rowMarks)                rowMarks = NIL;            else                rowMarks = root->rowMarks;            plan = (Plan *) make_modifytable(parse->commandType,                                             parse->canSetTag,                                       list_make1_int(parse->resultRelation),                                             list_make1(plan),                                             returningLists,                                             rowMarks,                                             SS_assign_special_param(root));        }    }

 由于 上面的 parse->resultRelation 是false。 所以,就变成了:

else    {        plan = grouping_planner(root, tuple_fraction);        /* If it's not SELECT, we need a ModifyTable node */        if (parse->commandType != CMD_SELECT)        {            List       *returningLists;            List       *rowMarks;            /*             * Set up the RETURNING list-of-lists, if needed.             */            if (parse->returningList)                returningLists = list_make1(parse->returningList);            else                returningLists = NIL;            /*             * If there was a FOR UPDATE/SHARE clause, the LockRows node will             * have dealt with fetching non-locked marked rows, else we need             * to have ModifyTable do that.             */            if (parse->rowMarks)                rowMarks = NIL;            else                rowMarks = root->rowMarks;            plan = (Plan *) make_modifytable(parse->commandType,                                             parse->canSetTag,                                       list_make1_int(parse->resultRelation),                                             list_make1(plan),                                             returningLists,                                             rowMarks,                                             SS_assign_special_param(root));        }    }

又由于 parse->commandType != CMD_SELECT 不成立,所以可以简化为:

else    {        plan = grouping_planner(root, tuple_fraction);                ...        }
 
 
 
 
 
 
 
 

转载地址:http://fqcol.baihongyu.com/

你可能感兴趣的文章
Redis设计与实现笔记
查看>>
rip汇总前后路由区别
查看>>
一致性Hash算法
查看>>
nmon
查看>>
×××全新升级以提升用户体验
查看>>
js 创建类
查看>>
调整实例恢复时间
查看>>
shell中$0,$?,$!等的特殊用法
查看>>
蓝牙协议栈代码分析
查看>>
我的友情链接
查看>>
几款常用幻灯片制作软件对比
查看>>
Java 代理模式和装饰者模式的区别
查看>>
php json_encode不转义中文字符
查看>>
征服变色龙-OpenSUSE
查看>>
Mysql 优化学习
查看>>
linux下升级python
查看>>
我的友情链接
查看>>
自定义圆形或圆角imageview
查看>>
RDD
查看>>
如何轻松又安全的备份自己的网站数据?
查看>>