greenplum中的Instrumentation统计数据

简介:

版本号

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

void
PortalStart(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

void
ExecutorStart(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 void
InitPlan(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

bool
PortalRun(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 int64
PortalRunSelect(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

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

PortalCleanup

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

ExecutorEnd

void
ExecutorEnd(QueryDesc *queryDesc)
{
    // 通过hook这个可以获得相关的统计数据
    if (query_info_collect_hook)
        (*query_info_collect_hook)(METRICS_QUERY_DONE, queryDesc);
}
目录
相关文章
|
存储 SQL 监控
22 PostgreSQL 监控3PostgreSQL 性能快照和图形化分析工具 pg_stats_info 的使用|学习笔记
快速学习22 PostgreSQL 监控3PostgreSQL 性能快照和图形化分析工具 pg_stats_info 的使用
896 0
22 PostgreSQL 监控3PostgreSQL 性能快照和图形化分析工具 pg_stats_info 的使用|学习笔记
|
1月前
|
监控 API Apache
实战!配置DataDog监控Apache Hudi应用指标
实战!配置DataDog监控Apache Hudi应用指标
21 0
|
SQL 缓存 监控
PostgreSQL 监控1统计进程和统计信息的解读|学习笔记(二)
快速学习PostgreSQL 监控1统计进程和统计信息的解读
317 0
PostgreSQL 监控1统计进程和统计信息的解读|学习笔记(二)
|
SQL 监控 IDE
PostgreSQL监控1统计进程和统计信息的解读|学习笔记(一)
快速学习PostgreSQL监控1统计进程和统计信息的解读
477 0
PostgreSQL监控1统计进程和统计信息的解读|学习笔记(一)
|
Web App开发 JSON 监控
Sentry 监控 - Discover 大数据查询分析引擎
Sentry 监控 - Discover 大数据查询分析引擎
300 0
Sentry 监控 - Discover 大数据查询分析引擎
|
存储 缓存 JSON
Sentry 监控 - Distributed Tracing 分布式跟踪
Sentry 监控 - Distributed Tracing 分布式跟踪
265 0
Sentry 监控 - Distributed Tracing 分布式跟踪
|
存储 SQL 分布式计算
如何用 Uber JVM Profiler 等可视化工具监控 Spark 应用程序?
  关键要点   持续可靠地运行 Spark 应用程序是一项具有挑战性的任务,而且需要一个良好的性能监控系统。   - 在设计性能监控系统时有三个目标——收集服务器和应用程序指标、在时序数据库中存储指标,并提供用于数据可视化的仪表盘。   Uber JVM Profiler 被用于监控 Spark 应用程序,用到的其他技术还有 InfluxDB(用于存储时序数据)和 Grafana(数据可视化工具)。性能监控系统可帮助 DevOps 团队有效地监控系统,用以满足应用程序的合规性和 SLA。
233 0
|
SQL 存储 缓存
EMR Spark-SQL性能极致优化揭秘 Native Codegen Framework
EMR团队探索并开发了SparkSQL Native Codegen框架,为SparkSQL换了引擎,新引擎带来最高4倍性能提升,为EMR再次获取世界第一立下汗马功劳。来自阿里云EMR团队的周克勇将详细介绍Native Codegen框架。
EMR Spark-SQL性能极致优化揭秘 Native Codegen Framework
|
分布式计算 大数据 Spark
7月30日产品直播【EMR Spark-SQL性能极致优化揭秘 Native Codegen Framework】
EMR团队探索并开发了SparkSQL Native Codegen框架,为SparkSQL换了引擎,新引擎带来最高4倍性能提升,为EMR再次获取世界第一立下汗马功劳,本次直播将详细介绍Native Codegen框架。
7月30日产品直播【EMR Spark-SQL性能极致优化揭秘 Native Codegen Framework】