博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
greenplum中的Instrumentation统计数据
阅读量:6566 次
发布时间:2019-06-24

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

版本号

PostgreSQL 8.3.23 (Greenplum Database 5.0.0 build dev)


设置gp_enable_query_metrics

gpconfig -c gp_enable_query_metrics -v on    //设置gpstop -r    //重启

hook

query_info_collect_hook可用于获取queryDesc相关信息

相关代码

以"SELECT * from instrument_test where id>1000 order by id limit 1000;"为例

PortalStart

voidPortalStart(Portal portal, ParamListInfo params, Snapshot snapshot,            const char *seqServerHost, int seqServerPort, QueryDispatchDesc *ddesc){    PG_TRY();    {        switch (portal->strategy)        {            case PORTAL_ONE_SELECT:                /*                  * #define GP_INSTRUMENT_OPTS (gp_enable_query_metrics ? INSTRUMENT_ROWS : INSTRUMENT_NONE)                 * 因为开启了 gp_enable_query_metrics, queryDesc->instrument_options被设置                 * 此处可以在gdb上设置 set var queryDesc->instrument_options=INSTRUMENT_ALL(0x7FFFFFFF),                 * 以查看greenplum的处理                 */                queryDesc = CreateQueryDesc((PlannedStmt *) linitial(portal->stmts),                                            portal->sourceText,                                            (gp_select_invisible ? SnapshotAny : ActiveSnapshot),                                            InvalidSnapshot,                                            None_Receiver,                                            params,                                            GP_INSTRUMENT_OPTS);                                    // 这是运行时可以修改queryDesc->instrument_options的hook                                        if (query_info_collect_hook)                    (*query_info_collect_hook)(METRICS_QUERY_SUBMIT, queryDesc);                                    ExecutorStart(queryDesc, eflags);                                portal->queryDesc = queryDesc;        }    }}

ExecutorStart

voidExecutorStart(QueryDesc *queryDesc, int eflags){    EState       *estate;        // 同样是运行时可以修改queryDesc->instrument_options的hook    if (query_info_collect_hook)        (*query_info_collect_hook)(METRICS_QUERY_START, queryDesc);        // 把queryDesc->instrument_options赋值给estate->es_instrument    estate->es_instrument = queryDesc->instrument_options;        PG_TRY();    {        InitPlan(queryDesc, eflags);    }}

InitPlan

static voidInitPlan(QueryDesc *queryDesc, int eflags){    PlanState  *planstate;        planstate = ExecInitNode(start_plan_node, estate, eflags);    queryDesc->planstate = planstate;    if (query_info_collect_hook)        (*query_info_collect_hook)(METRICS_PLAN_NODE_INITIALIZE, queryDesc);}

ExecInitNode

PlanState *ExecInitNode(Plan *node, EState *estate, int eflags){    PlanState  *result;    // 如果前面设置了queryDesc->instrument_options,这里会为queryDesc->planstate->instrument分配内存    if (estate->es_instrument && result != NULL)        result->instrument = GpInstrAlloc(node, estate->es_instrument);            return result;}

GpInstrAlloc

Instrumentation *GpInstrAlloc(const Plan *node, int instrument_options){    Instrumentation *instr = NULL;    if (shouldPickInstrInShmem(nodeTag(node)))        instr = pickInstrFromShmem(node, instrument_options);    return instr;}

pickInstrFromShmem

static Instrumentation *pickInstrFromShmem(const Plan *plan, int instrument_options){    Instrumentation *instr = NULL;    // 此处省略instr的处理步骤        /*      * 如果前面设置了set var queryDesc->instrument_options=INSTRUMENT_ALL(0x7FFFFFFF),     * 则这里会设置need_timer=true;     * need_cdb用于EXPLAIN ANALYZE     */    if (NULL != instr && instrument_options & (INSTRUMENT_TIMER | INSTRUMENT_CDB))    {        instr->need_timer = (instrument_options & INSTRUMENT_TIMER) != 0;        instr->need_cdb = (instrument_options & INSTRUMENT_CDB) != 0;    }    return instr;}

PortalRun

boolPortalRun(Portal portal, int64 count, bool isTopLevel,          DestReceiver *dest, DestReceiver *altdest,          char *completionTag){    PG_TRY();    {        switch (portal->strategy)        {            case PORTAL_ONE_SELECT:                (void) PortalRunSelect(portal, true, count, dest);        }    }}

PortalRunSelect

static int64PortalRunSelect(Portal portal,                bool forward,                int64 count,                DestReceiver *dest){    uint64        nprocessed;        if (forward)    {        if (portal->holdStore)        else        {            ExecutorRun(queryDesc, direction, count);        }    }}

ExecutorRun

TupleTableSlot *ExecutorRun(QueryDesc *queryDesc,            ScanDirection direction, long count){    TupleTableSlot *result = NULL;        PG_TRY();    {        else if (exec_identity == GP_ROOT_SLICE)        {            result = ExecutePlan(estate,                                 queryDesc->planstate,                                 operation,                                 count,                                 direction,                                 dest);        }    }}

ExecutePlan

static TupleTableSlot *ExecutePlan(EState *estate,            PlanState *planstate,            CmdType operation,            long numberTuples,            ScanDirection direction,            DestReceiver *dest){    for (;;)    {        if (estate->es_useEvalPlan)        {        }        else            planSlot = ExecProcNode(planstate);    }}

ExecProcNode

TupleTableSlot *ExecProcNode(PlanState *node){    /*      * 如果前面用gdb设置了queryDesc->instrument_options=0x7FFFFFFF,     * 此处在获取一行tuple之前设置instrument->starttime      */    if (node->instrument)        INSTR_START_NODE(node->instrument);

Screenshot_from_2018_08_30_11_46_53

/*      * 此处会将获取每行tuple的时间累加到node->instrument->counter     */    if (node->instrument)        INSTR_STOP_NODE(node->instrument, TupIsNull(result) ? 0 : 1);

Screenshot_from_2018_08_30_14_24_55

}

PortalDrop

voidPortalDrop(Portal portal, bool isTopCommit){    if (portal->cleanup)        (*portal->cleanup) (portal); // 通过回调进入PortalCleanup}

PortalCleanup

voidPortalCleanup(Portal portal){     queryDesc = PortalGetQueryDesc(portal);    if (queryDesc)    { // queryDesc被释放        portal->queryDesc = NULL;        PG_TRY();        {            ExecutorEnd(queryDesc);        }    }}

ExecutorEnd

voidExecutorEnd(QueryDesc *queryDesc){    // 通过hook这个可以获得相关的统计数据    if (query_info_collect_hook)        (*query_info_collect_hook)(METRICS_QUERY_DONE, queryDesc);}

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

你可能感兴趣的文章
django forms模块使用
查看>>
FreeBSD IPFW 防火墙的安装和设置
查看>>
Linux分区和文件系统 ⑥
查看>>
ClipDrawable--水漫起来的效果
查看>>
osd内的pg数量
查看>>
shell脚本与mysql交互方法汇总
查看>>
Cron 表达式详解和案例
查看>>
Android - 软件自动更新的实现
查看>>
oracle数据库远程不落地导入本地数据库
查看>>
Unix调试的瑞士军刀:lsof(转)
查看>>
dns相关内容
查看>>
JavaScript骚操作
查看>>
MySQL的主从复制与读写分离原理
查看>>
luaCPU性能测试
查看>>
mysql优化
查看>>
【批处理】for循环中产生不同的随机数
查看>>
Gradle -help
查看>>
/etc/security/limits.conf
查看>>
js 框架
查看>>
android 实现ListView中添加RaidoButton单选
查看>>