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

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

回溯:PortalRun --> PortalRunSelect

boolPortalRun(Portal portal, long count, bool isTopLevel,          DestReceiver *dest, DestReceiver *altdest,          char *completionTag){    ...    portal->status = PORTAL_ACTIVE;    ...    PG_TRY();    {        ActivePortal = portal;        CurrentResourceOwner = portal->resowner;        PortalContext = PortalGetHeapMemory(portal);        MemoryContextSwitchTo(PortalContext);        switch (portal->strategy)        {            case PORTAL_ONE_SELECT:            case PORTAL_ONE_RETURNING:            case PORTAL_ONE_MOD_WITH:            case PORTAL_UTIL_SELECT:                ...                /*                 * Now fetch desired portion of results.                 */                nprocessed = PortalRunSelect(portal, true, count, dest);                ...                break;            case PORTAL_MULTI_QUERY:                ...                break;            default:                ...                break;        }    }    PG_CATCH();    {        ...        PG_RE_THROW();    }    PG_END_TRY();    ...    return result;}

再回溯:

static voidexec_simple_query(const char *query_string){    ...    parsetree_list = pg_parse_query(query_string);    ...    /*     * Run through the raw parsetree(s) and process each one.     */    foreach(parsetree_item, parsetree_list)    {        ...        querytree_list = pg_analyze_and_rewrite(parsetree, query_string,NULL, 0);        plantree_list = pg_plan_queries(querytree_list, 0, NULL);        ...        portal = CreatePortal("", true, true);        ...        PortalDefineQuery(portal,                          NULL,                          query_string,                          commandTag,                          plantree_list,                          NULL);        ...        PortalStart(portal, NULL, 0, snapshot_set);        ...        /*         * Run the portal to completion, and then drop it (and the receiver).         */        (void) PortalRun(portal,                         FETCH_ALL,                         isTopLevel,                         receiver,                         receiver,                         completionTag);        ...    }                            /* end loop over parsetrees */    ...}

 从源代码中查看的结果是:对于我的普通查询,InitScanRelation中对 ss_currentScanDesc 进行了赋值。

经过调查,路径是这样的:

PortalStart-->ExecutorStart-->Standard_ExecutorStart-->InitPlan-->ExecInitNode-->ExecInitSeqscan-->InitScanRelation

再回过头来回味:

PlanState *ExecInitNode(Plan *node, EState *estate, int eflags){    PlanState  *result;    List       *subps;    ListCell   *l;    /*     * do nothing when we get to the end of a leaf on tree.     */    if (node == NULL)        return NULL;    switch (nodeTag(node))    {            /*             * control nodes             */        case T_Result:            result = (PlanState *) ExecInitResult((Result *) node,                                                  estate, eflags);            break;        ..            /*             * scan nodes             */        case T_SeqScan:            result = (PlanState *) ExecInitSeqScan((SeqScan *) node,                                                   estate, eflags);            break;        case T_IndexScan:            result = (PlanState *) ExecInitIndexScan((IndexScan *) node,                                                     estate, eflags);            break;        case T_IndexOnlyScan:            result = (PlanState *) ExecInitIndexOnlyScan((IndexOnlyScan *) node,                                                         estate, eflags);            break;        ...    }    /*     * Initialize any initPlans present in this node.  The planner put them in     * a separate list for us.     */    subps = NIL;    foreach(l, node->initPlan)    {        SubPlan    *subplan = (SubPlan *) lfirst(l);        SubPlanState *sstate;        Assert(IsA(subplan, SubPlan));        sstate = ExecInitSubPlan(subplan, result);        subps = lappend(subps, sstate);    }    result->initPlan = subps;    /* Set up instrumentation for this node if requested */    if (estate->es_instrument)        result->instrument = InstrAlloc(1, estate->es_instrument);    return result;}

从上面可以看到,在进行  ExecInitNode 的时候,根据tag 进行了特定的初始化。

ExecInitSeqscan:

/* ---------------------------------------------------------------- *        ExecInitSeqScan * ---------------------------------------------------------------- */SeqScanState *ExecInitSeqScan(SeqScan *node, EState *estate, int eflags){    SeqScanState *scanstate;    /*     * Once upon a time it was possible to have an outerPlan of a SeqScan, but     * not any more.     */    Assert(outerPlan(node) == NULL);    Assert(innerPlan(node) == NULL);    /*     * create state structure     */    scanstate = makeNode(SeqScanState);    scanstate->ps.plan = (Plan *) node;    scanstate->ps.state = estate;    /*     * Miscellaneous initialization     *     * create expression context for node     */    ExecAssignExprContext(estate, &scanstate->ps);    /*     * initialize child expressions     */    scanstate->ps.targetlist = (List *)        ExecInitExpr((Expr *) node->plan.targetlist,                     (PlanState *) scanstate);    scanstate->ps.qual = (List *)        ExecInitExpr((Expr *) node->plan.qual,                     (PlanState *) scanstate);    /*     * tuple table initialization     */    ExecInitResultTupleSlot(estate, &scanstate->ps);    ExecInitScanTupleSlot(estate, scanstate);    /*     * initialize scan relation     */    InitScanRelation(scanstate, estate);    scanstate->ps.ps_TupFromTlist = false;    /*     * Initialize result tuple type and projection info.     */    ExecAssignResultTypeFromTL(&scanstate->ps);    ExecAssignScanProjectionInfo(scanstate);    return scanstate;}

 与此相对的,还有另外一条路径,非常类似:

PortalRun-->

PortalRunSelect-->ExecutorRun-->Standard_ExecutorRun-->ExecutePlan-->ExecProcNode-->ExecSeqscan

当初在 PortalStart 的时候按 Tag来分别进行初始化,在 PortalRun的时候,也要按照 Tag 来分别执行各自合适的Scan(物理磁盘扫描)。

TupleTableSlot *ExecProcNode(PlanState *node){    TupleTableSlot *result;    CHECK_FOR_INTERRUPTS();    if (node->chgParam != NULL) /* something changed */        ExecReScan(node);        /* let ReScan handle this */    if (node->instrument)        InstrStartNode(node->instrument);    switch (nodeTag(node))    {            /*             * control nodes             */        case T_ResultState:            result = ExecResult((ResultState *) node);            break;        ...            /*             * scan nodes             */        case T_SeqScanState:            result = ExecSeqScan((SeqScanState *) node);            break;        ...    }    if (node->instrument)        InstrStopNode(node->instrument, TupIsNull(result) ? 0.0 : 1.0);    return result;}

 

转载于:https://www.cnblogs.com/gaojian/archive/2013/06/03/3115284.html

你可能感兴趣的文章
iOS基础-UIKit框架-多控制器管理-实例:qq界面框架
查看>>
IOS-每个程序员的编程之路上都应该看这11本书
查看>>
自定义tabbar(纯代码)
查看>>
小程序底部导航栏
查看>>
ibatis学习笔记
查看>>
18-ES6(1)
查看>>
poj1611 简单并查集
查看>>
Ubuntu 14.04下安装CUDA8.0
查看>>
跨平台开发 -- C# 使用 C/C++ 生成的动态链接库
查看>>
C# BS消息推送 SignalR介绍(一)
查看>>
WPF星空效果
查看>>
WPF Layout 系统概述——Arrange
查看>>
PIGOSS
查看>>
几款Http小服务器
查看>>
iOS 数组排序
查看>>
第三节
查看>>
PHP结合MYSQL记录结果分页呈现(比较实用)
查看>>
Mysql支持的数据类型
查看>>
openSuse beginner
查看>>
Codeforces 620E(线段树+dfs序+状态压缩)
查看>>