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);
}
目录
相关文章
|
6月前
|
SQL Oracle Java
实时计算 Flink版产品使用问题之采集Oracle数据时,为什么无法采集到其他TABLESPACE的表
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
8月前
|
运维 监控 Java
性能监控之 Java Metrics 度量包
【6月更文挑战10天】标题性能监控之 Java Metrics 度量包
176 2
|
9月前
|
存储 Prometheus 监控
性能监控之国产时序库TDengine TDinsight dashboard 指标解析
【2月更文挑战第1天】性能监控之国产时序库TDengine TDinsight dashboard 指标解析
798 1
性能监控之国产时序库TDengine TDinsight dashboard 指标解析
|
SQL 监控 Oracle
Oracle 性能监控统计工具 mystats脚本
看看这个工具的介绍就知道这个工具是很牛的,因为它是在两个牛人的工具是改进的,一出生就有贵族血统呀!
141 0
|
SQL 监控 Oracle
PostgreSQL pgcenter - 采样、统计、性能诊断、profile、cli小工具
标签 PostgreSQL , pgcenter , pg_top , awr , perf insight , 等待事件 , perf , profile , 采样 , 统计信息 背景 PostgreSQL 性能诊断的方法很多: 例如: 1、函数的性能诊断,PROFILE。 《PostgreSQL 函数调试、诊断、优化 & auto_explain & plpro
2098 0
|
SQL 索引
profiling分析查询
profiling分析查询
120 0
|
SQL 存储 运维
【新功能发布】Hologres Worker级别监控指标透出,提升自诊断能力
本文将会介绍Hologres在2022年7月新发布的监控指标,以及对应的排查手段。
1237 0
【新功能发布】Hologres Worker级别监控指标透出,提升自诊断能力
|
Web App开发 JSON 监控
Sentry 监控 - Discover 大数据查询分析引擎
Sentry 监控 - Discover 大数据查询分析引擎
371 0
Sentry 监控 - Discover 大数据查询分析引擎
|
存储 SQL 分布式计算
如何用 Uber JVM Profiler 等可视化工具监控 Spark 应用程序?
  关键要点   持续可靠地运行 Spark 应用程序是一项具有挑战性的任务,而且需要一个良好的性能监控系统。   - 在设计性能监控系统时有三个目标——收集服务器和应用程序指标、在时序数据库中存储指标,并提供用于数据可视化的仪表盘。   Uber JVM Profiler 被用于监控 Spark 应用程序,用到的其他技术还有 InfluxDB(用于存储时序数据)和 Grafana(数据可视化工具)。性能监控系统可帮助 DevOps 团队有效地监控系统,用以满足应用程序的合规性和 SLA。
287 0