本文共 6103 字,大约阅读时间需要 20 分钟。
PostgreSQL 8.3.23 (Greenplum Database 5.0.0 build dev)
gpconfig -c gp_enable_query_metrics -v on //设置gpstop -r //重启
query_info_collect_hook可用于获取queryDesc相关信息
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; } }}
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); }}
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);}
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;}
Instrumentation *GpInstrAlloc(const Plan *node, int instrument_options){ Instrumentation *instr = NULL; if (shouldPickInstrInShmem(nodeTag(node))) instr = pickInstrFromShmem(node, instrument_options); return instr;}
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;}
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); } }}
static int64PortalRunSelect(Portal portal, bool forward, int64 count, DestReceiver *dest){ uint64 nprocessed; if (forward) { if (portal->holdStore) else { ExecutorRun(queryDesc, direction, count); } }}
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); } }}
static TupleTableSlot *ExecutePlan(EState *estate, PlanState *planstate, CmdType operation, long numberTuples, ScanDirection direction, DestReceiver *dest){ for (;;) { if (estate->es_useEvalPlan) { } else planSlot = ExecProcNode(planstate); }}
TupleTableSlot *ExecProcNode(PlanState *node){ /* * 如果前面用gdb设置了queryDesc->instrument_options=0x7FFFFFFF, * 此处在获取一行tuple之前设置instrument->starttime */ if (node->instrument) INSTR_START_NODE(node->instrument);
/* * 此处会将获取每行tuple的时间累加到node->instrument->counter */ if (node->instrument) INSTR_STOP_NODE(node->instrument, TupIsNull(result) ? 0 : 1);
}
voidPortalDrop(Portal portal, bool isTopCommit){ if (portal->cleanup) (*portal->cleanup) (portal); // 通过回调进入PortalCleanup}
voidPortalCleanup(Portal portal){ queryDesc = PortalGetQueryDesc(portal); if (queryDesc) { // queryDesc被释放 portal->queryDesc = NULL; PG_TRY(); { ExecutorEnd(queryDesc); } }}
voidExecutorEnd(QueryDesc *queryDesc){ // 通过hook这个可以获得相关的统计数据 if (query_info_collect_hook) (*query_info_collect_hook)(METRICS_QUERY_DONE, queryDesc);}
转载地址:http://eocjo.baihongyu.com/