本篇内容主要讲解“postgresql中用于初始化查询执行计划函数是哪个”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Postgresql中用于初始化查询执行计
本篇内容主要讲解“postgresql中用于初始化查询执行计划函数是哪个”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Postgresql中用于初始化查询执行计划函数是哪个”吧!
EState
执行器在调用时的主要工作状态
typedef struct EState
{
nodeTag type;//标记
//所有查询类型的基础状态
ScanDirection es_direction;
Snapshot es_snapshot;
Snapshot es_crosscheck_snapshot;
List *es_range_table;
struct RangeTblEntry **es_range_table_array;
Index es_range_table_size;
Relation *es_relations;
struct ExecRowMark **es_rowmarks;
PlannedStmt *es_plannedstmt;
const char *es_sourceText;
JunkFilter *es_junkFilter;
//如查询可以插入/删除元组,这里记录了命令ID
CommandId es_output_cid;
//insert/update/delete 目标表信息
ResultRelInfo *es_result_relations;
int es_num_result_relations;
ResultRelInfo *es_result_relation_info;
ResultRelInfo *es_root_result_relations;
int es_num_root_result_relations;
List *es_tuple_routing_result_relations;
//用于触发触发器的信息
List *es_trig_target_relations;
TupleTableSlot *es_trig_tuple_slot;
TupleTableSlot *es_trig_oldtup_slot;
TupleTableSlot *es_trig_newtup_slot;
//参数信息
ParamListInfo es_param_list_info;
ParamExecData *es_param_exec_vals;
QueryEnvironment *es_queryEnv;
//其他工作状态
MemoryContext es_query_cxt;
List *es_tupleTable;
uint64 es_processed;
Oid es_lastoid;
int es_top_eflags;
int es_instrument;
bool es_finished;
List *es_exprcontexts;
List *es_subplanstates;
List *es_auxmodifytables;
ExprContext *es_per_tuple_exprcontext;
HeapTuple *es_epQtuple;
bool *es_epqTupleSet;
bool *es_epqScanDone;
bool es_use_parallel_mode;
//用于并行执行的每个查询共享内存区域。
struct dsa_area *es_query_dsa;
int es_jit_flags;
struct JitContext *es_jit;
struct JitInstrumentation *es_jit_worker_instr;
} EState;
PlanState
PlanState是所有PlanState-type节点的虚父类(请参照面向对象的虚类)
typedef struct PlanState
{
NodeTag type;//节点类型
Plan *plan;
EState *state;
ExecProcNodeMtd ExecProcNode;
ExecProcNodeMtd ExecProcNodeReal;
Instrumentation *instrument;
WorkerInstrumentation *worker_instrument;
//worker相应的JIT instrumentation
struct SharedJitInstrumentation *worker_jit_instrument;
ExprState *qual;
struct PlanState *lefttree;
struct PlanState *righttree;
List *initPlan;
List *subPlan;
Bitmapset *chgParam;
TupleDesc ps_ResultTupleDesc;
TupleTableSlot *ps_ResultTupleSlot;
ExprContext *ps_ExprContext;
ProjectionInfo *ps_ProjInfo;
TupleDesc scandesc;
} PlanState;
InitPlan函数初始化查询执行计划:打开文件/分配存储空间并启动规则管理器.
static void
InitPlan(QueryDesc *queryDesc, int eflags)
{
CmdType operation = queryDesc->operation;//命令类型
PlannedStmt *plannedstmt = queryDesc->plannedstmt;//已规划的语句指针
Plan *plan = plannedstmt->planTree;//计划树
List *rangeTable = plannedstmt->rtable;//RTE链表
EState *estate = queryDesc->estate;//参见数据结构
PlanState *planstate;//参见数据结构
TupleDesc tupType;//参见数据结构
ListCell *l;
int i;
ExecCheckRTPerms(rangeTable, true);
ExecInitRangeTable(estate, rangeTable);
estate->es_plannedstmt = plannedstmt;
if (plannedstmt->resultRelations)//存在resultRelations
{
List *resultRelations = plannedstmt->resultRelations;//结果Relation链表
int numResultRelations = list_length(resultRelations);//链表大小
ResultRelInfo *resultRelInfos;//ResultRelInfo数组
ResultRelInfo *resultRelInfo;//ResultRelInfo指针
resultRelInfos = (ResultRelInfo *)
palloc(numResultRelations * sizeof(ResultRelInfo));//分配空间
resultRelInfo = resultRelInfos;//指针赋值
foreach(l, resultRelations)//遍历链表
{
Index resultRelationIndex = lfirst_int(l);
Relation resultRelation;
resultRelation = ExecGetRangeTableRelation(estate,
resultRelationIndex);//获取结果Relation
InitResultRelInfo(resultRelInfo,
resultRelation,
resultRelationIndex,
NULL,
estate->es_instrument);//初始化ResultRelInfo
resultRelInfo++;//处理下一个ResultRelInfo
}
estate->es_result_relations = resultRelInfos;//赋值
estate->es_num_result_relations = numResultRelations;
//设置es_result_relation_info为NULL,除了ModifyTable
estate->es_result_relation_info = NULL;
if (plannedstmt->rootResultRelations)//存在rootResultRelations(并行处理)
{
int num_roots = list_length(plannedstmt->rootResultRelations);
resultRelInfos = (ResultRelInfo *)
palloc(num_roots * sizeof(ResultRelInfo));
resultRelInfo = resultRelInfos;
foreach(l, plannedstmt->rootResultRelations)
{
Index resultRelIndex = lfirst_int(l);
Relation resultRelDesc;
resultRelDesc = ExecGetRangeTableRelation(estate,
resultRelIndex);
InitResultRelInfo(resultRelInfo,
resultRelDesc,
resultRelIndex,
NULL,
estate->es_instrument);
resultRelInfo++;
}
estate->es_root_result_relations = resultRelInfos;
estate->es_num_root_result_relations = num_roots;
}
else
{
estate->es_root_result_relations = NULL;
estate->es_num_root_result_relations = 0;
}
}
else//不存在resultRelations
{
estate->es_result_relations = NULL;
estate->es_num_result_relations = 0;
estate->es_result_relation_info = NULL;
estate->es_root_result_relations = NULL;
estate->es_num_root_result_relations = 0;
}
if (plannedstmt->rowMarks)//如存在rowMarks
{
estate->es_rowmarks = (ExecRowMark **)
palloc0(estate->es_range_table_size * sizeof(ExecRowMark *));
foreach(l, plannedstmt->rowMarks)
{
PlanRowMark *rc = (PlanRowMark *) lfirst(l);
Oid relid;
Relation relation;
ExecRowMark *erm;
if (rc->isParent)
continue;
relid = exec_rt_fetch(rc->rti, estate)->relid;
switch (rc->markType)
{
case ROW_MARK_EXCLUSIVE:
case ROW_MARK_NOKEYEXCLUSIVE:
case ROW_MARK_SHARE:
case ROW_MARK_KEYSHARE:
case ROW_MARK_REFERENCE:
relation = ExecGetRangeTableRelation(estate, rc->rti);
break;
case ROW_MARK_COPY:
relation = NULL;
break;
default:
elog(ERROR, "unrecognized markType: %d", rc->markType);
relation = NULL;
break;
}
if (relation)
CheckValidRowMarkRel(relation, rc->markType);
erm = (ExecRowMark *) palloc(sizeof(ExecRowMark));
erm->relation = relation;
erm->relid = relid;
erm->rti = rc->rti;
erm->prti = rc->prti;
erm->rowmarkId = rc->rowmarkId;
erm->markType = rc->markType;
erm->strength = rc->strength;
erm->waitPolicy = rc->waitPolicy;
erm->erMactive = false;
ItemPointerSetInvalid(&(erm->curCtid));
erm->ermExtra = NULL;
Assert(erm->rti > 0 && erm->rti <= estate->es_range_table_size &&
estate->es_rowmarks[erm->rti - 1] == NULL);
estate->es_rowmarks[erm->rti - 1] = erm;
}
}
estate->es_tupleTable = NIL;
estate->es_trig_tuple_slot = NULL;
estate->es_trig_oldtup_slot = NULL;
estate->es_trig_newtup_slot = NULL;
//标记EvalPlanQual为非活动模式
estate->es_epqTuple = NULL;
estate->es_epqTupleSet = NULL;
estate->es_epqScanDone = NULL;
Assert(estate->es_subplanstates == NIL);
i = 1;
foreach(l, plannedstmt->subplans)//遍历subplans
{
Plan *subplan = (Plan *) lfirst(l);
PlanState *subplanstate;
int sp_eflags;
sp_eflags = eflags
& (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA);//设置sp_eflags
if (bms_is_member(i, plannedstmt->rewindPlanIDs))
sp_eflags |= EXEC_FLAG_REWIND;
subplanstate = ExecInitNode(subplan, estate, sp_eflags);//执行Plan节点初始化过程
estate->es_subplanstates = lappend(estate->es_subplanstates,
subplanstate);
i++;
}
planstate = ExecInitNode(plan, estate, eflags);//执行Plan节点初始化过程
tupType = ExecGetResultType(planstate);
if (operation == CMD_SELECT)//SELECT命令
{
bool junk_filter_needed = false;
ListCell *tlist;
foreach(tlist, plan->targetlist)//遍历tlist
{
TargetEntry *tle = (TargetEntry *) lfirst(tlist);
if (tle->resjunk)//如需要垃圾过滤器
{
junk_filter_needed = true;//设置为T
break;
}
}
if (junk_filter_needed)
{
JunkFilter *j;
j = ExecInitJunkFilter(planstate->plan->targetlist,
tupType->tdhasoid,
ExecInitExtraTupleSlot(estate, NULL));//初始化
estate->es_junkFilter = j;
//期望返回已清理的元组类型
tupType = j->jf_cleanTupType;
}
}
//赋值
queryDesc->tupDesc = tupType;
queryDesc->planstate = planstate;
}
测试脚本如下
testdb=# explain select dw.*,grjf.grbh,grjf.xm,grjf.ny,grjf.je
testdb-# from t_dwxx dw,lateral (select gr.grbh,gr.xm,jf.ny,jf.je
testdb(# from t_grxx gr inner join t_jfxx jf
testdb(# on gr.dwbh = dw.dwbh
testdb(# and gr.grbh = jf.grbh) grjf
testdb-# order by dw.dwbh;
QUERY PLAN
------------------------------------------------------------------------------------------
Sort (cost=20070.93..20320.93 rows=100000 width=47)
Sort Key: dw.dwbh
-> Hash Join (cost=3754.00..8689.61 rows=100000 width=47)
Hash Cond: ((gr.dwbh)::text = (dw.dwbh)::text)
-> Hash Join (cost=3465.00..8138.00 rows=100000 width=31)
Hash Cond: ((jf.grbh)::text = (gr.grbh)::text)
-> Seq Scan on t_jfxx jf (cost=0.00..1637.00 rows=100000 width=20)
-> Hash (cost=1726.00..1726.00 rows=100000 width=16)
-> Seq Scan on t_grxx gr (cost=0.00..1726.00 rows=100000 width=16)
-> Hash (cost=164.00..164.00 rows=10000 width=20)
-> Seq Scan on t_dwxx dw (cost=0.00..164.00 rows=10000 width=20)
(11 rows)
启动gdb,设置断点,进入InitPlan
(gdb) b InitPlan
Breakpoint 1 at 0x6d9df2: file execMain.c, line 808.
(gdb) c
Continuing.
Breakpoint 1, InitPlan (queryDesc=0x20838b8, eflags=16) at execMain.c:808
warning: Source file is more recent than executable.
808 CmdType operation = queryDesc->operation;
输入参数
(gdb) p *queryDesc
$1 = {operation = CMD_SELECT, plannedstmt = 0x207e6c0,
sourceText = 0x1f96eb8 "select dw.*,grjf.grbh,grjf.xm,grjf.ny,grjf.je \nfrom t_dwxx dw,lateral (select gr.grbh,gr.xm,jf.ny,jf.je \n", ' ' <repeats 24 times>, "from t_grxx gr inner join t_jfxx jf \n", ' ' <repeats 34 times>...,
snapshot = 0x1fba8e0, crosscheck_snapshot = 0x0, dest = 0xf8f280 <donothingDR>, params = 0x0, queryEnv = 0x0,
instrument_options = 0, tupDesc = 0x0, estate = 0x207f898, planstate = 0x0, already_executed = false, totaltime = 0x0}
(gdb) p eflags
$2 = 16
变量赋值,PlannedStmt的详细数据结构先前章节已有解释,请参见相关章节.
(gdb) n
809 PlannedStmt *plannedstmt = queryDesc->plannedstmt;
(gdb)
810 Plan *plan = plannedstmt->planTree;
(gdb)
811 List *rangeTable = plannedstmt->rtable;
(gdb) n
812 EState *estate = queryDesc->estate;
(gdb)
821 ExecCheckRTPerms(rangeTable, true);
(gdb) p *plannedstmt
$3 = {type = T_PlannedStmt, commandType = CMD_SELECT, queryId = 0, hasReturning = false, hasModifyinGCTE = false,
canSetTag = true, transientPlan = false, dependsOnRole = false, parallelModeNeeded = false, jitFlags = 0,
planTree = 0x20788f8, rtable = 0x207c568, resultRelations = 0x0, nonleafResultRelations = 0x0, rootResultRelations = 0x0,
subplans = 0x0, rewindPlanIDs = 0x0, rowMarks = 0x0, relationOids = 0x207c5c8, invalItems = 0x0, paramExecTypes = 0x0,
utilityStmt = 0x0, stmt_location = 0, stmt_len = 313}
(gdb) p *plan
$4 = {type = T_Sort, startup_cost = 20070.931487218411, total_cost = 20320.931487218411, plan_rows = 100000,
plan_width = 47, parallel_aware = false, parallel_safe = true, plan_node_id = 0, targetlist = 0x207cc28, qual = 0x0,
lefttree = 0x207c090, righttree = 0x0, initPlan = 0x0, extParam = 0x0, allParam = 0x0}
(gdb) p *estate
$5 = {type = T_EState, es_direction = ForwardScanDirection, es_snapshot = 0x1fba8e0, es_crosscheck_snapshot = 0x0,
es_range_table = 0x0, es_plannedstmt = 0x0,
es_sourceText = 0x1f96eb8 "select dw.*,grjf.grbh,grjf.xm,grjf.ny,grjf.je \nfrom t_dwxx dw,lateral (select gr.grbh,gr.xm,jf.ny,jf.je \n", ' ' <repeats 24 times>, "from t_grxx gr inner join t_jfxx jf \n", ' ' <repeats 34 times>...,
es_junkFilter = 0x0, es_output_cid = 0, es_result_relations = 0x0, es_num_result_relations = 0,
es_result_relation_info = 0x0, es_root_result_relations = 0x0, es_num_root_result_relations = 0,
es_tuple_routing_result_relations = 0x0, es_trig_target_relations = 0x0, es_trig_tuple_slot = 0x0,
es_trig_oldtup_slot = 0x0, es_trig_newtup_slot = 0x0, es_param_list_info = 0x0, es_param_exec_vals = 0x0,
es_queryEnv = 0x0, es_query_cxt = 0x207f780, es_tupleTable = 0x0, es_rowMarks = 0x0, es_processed = 0, es_lastoid = 0,
es_top_eflags = 16, es_instrument = 0, es_finished = false, es_exprcontexts = 0x0, es_subplanstates = 0x0,
es_auxmodifytables = 0x0, es_per_tuple_exprcontext = 0x0, es_epqTuple = 0x0, es_epqTupleSet = 0x0, es_epqScanDone = 0x0,
es_use_parallel_mode = false, es_query_dsa = 0x0, es_jit_flags = 0, es_jit = 0x0, es_jit_worker_instr = 0x0}
RTE链表,一共有5个Item,3个基础关系RTE_RELATION(1/3/4),1个RTE_SUBQUERY(2号),1个RTE_JOIN(5号)
(gdb) n
826 estate->es_range_table = rangeTable;
(gdb) p *rangeTable
$6 = {type = T_List, length = 5, head = 0x207c540, tail = 0x207cb28}
(gdb) p *(RangeTblEntry *)rangeTable->head->data.ptr_value
$9 = {type = T_RangeTblEntry, rtekind = RTE_RELATION, relid = 16734, relkind = 114 'r', tablesample = 0x0, subquery = 0x0,
security_barrier = false, jointype = JOIN_INNER, joinaliasvars = 0x0, functions = 0x0, funcordinality = false,
tablefunc = 0x0, values_lists = 0x0, ctename = 0x0, ctelevelsup = 0, self_reference = false, coltypes = 0x0,
coltypmods = 0x0, colcollations = 0x0, enrname = 0x0, enrtuples = 0, alias = 0x1f98448, eref = 0x1fbdd20,
lateral = false, inh = false, inFromCl = true, requiredPerms = 2, checkAsUser = 0, selectedCols = 0x2054de8,
insertedCols = 0x0, updatedCols = 0x0, securityQuals = 0x0}
...
没有结果Relation,执行相应的处理逻辑
(gdb)
835 if (plannedstmt->resultRelations)
(gdb) p plannedstmt->resultRelations
$14 = (List *) 0x0
(gdb) n
922 estate->es_result_relations = NULL;
(gdb)
923 estate->es_num_result_relations = 0;
(gdb)
924 estate->es_result_relation_info = NULL;
(gdb)
925 estate->es_root_result_relations = NULL;
(gdb)
926 estate->es_num_root_result_relations = 0;
不存在rowMarks(for update)
(gdb) n
939 foreach(l, plannedstmt->rowMarks)
(gdb) p plannedstmt->rowMarks
$15 = (List *) 0x0
(gdb) p plannedstmt->rowMarks
$16 = (List *) 0x0
(gdb) n
1000 estate->es_tupleTable = NIL;
执行赋值
(gdb) n
1001 estate->es_trig_tuple_slot = NULL;
(gdb)
1002 estate->es_trig_oldtup_slot = NULL;
...
没有subplans
(gdb) n
1017 foreach(l, plannedstmt->subplans)
(gdb) p *plannedstmt->subplans
Cannot access memory at address 0x0
(gdb) n
初始化节点(执行ExecInitNode)和获取TupleType
(gdb) n
1046 planstate = ExecInitNode(plan, estate, eflags);
(gdb) n
1051 tupType = ExecGetResultType(planstate);
(gdb)
1057 if (operation == CMD_SELECT)
(gdb) p *planstate
$17 = {type = T_SortState, plan = 0x20788f8, state = 0x207f898, ExecProcNode = 0x6e41bb <ExecProcNodeFirst>,
ExecProcNodeReal = 0x716144 <ExecSort>, instrument = 0x0, worker_instrument = 0x0, worker_jit_instrument = 0x0,
qual = 0x0, lefttree = 0x207fbc8, righttree = 0x0, initPlan = 0x0, subPlan = 0x0, chgParam = 0x0,
ps_ResultTupleSlot = 0x2090dc0, ps_ExprContext = 0x0, ps_ProjInfo = 0x0, scandesc = 0x208e920}
(gdb) p tupType
$18 = (TupleDesc) 0x20909a8
(gdb) p *tupType
$19 = {natts = 7, tdtypeid = 2249, tdtypmod = -1, tdhasoid = false, tdrefcount = -1, constr = 0x0, attrs = 0x20909c8}
判断是否需要垃圾过滤器
(gdb) n
1059 bool junk_filter_needed = false;
(gdb)
1062 foreach(tlist, plan->targetlist)
不需要junk filter
(gdb)
1073 if (junk_filter_needed)
赋值,结束调用
(gdb)
1087 queryDesc->tupDesc = tupType;
(gdb)
1088 queryDesc->planstate = planstate;
(gdb)
1089 }
(gdb)
standard_ExecutorStart (queryDesc=0x20838b8, eflags=16) at execMain.c:267
267 MemoryContextSwitchTo(oldcontext);
(gdb) p *queryDesc
$21 = {operation = CMD_SELECT, plannedstmt = 0x207e6c0,
sourceText = 0x1f96eb8 "select dw.*,grjf.grbh,grjf.xm,grjf.ny,grjf.je \nfrom t_dwxx dw,lateral (select gr.grbh,gr.xm,jf.ny,jf.je \n", ' ' <repeats 24 times>, "from t_grxx gr inner join t_jfxx jf \n", ' ' <repeats 34 times>...,
snapshot = 0x1fba8e0, crosscheck_snapshot = 0x0, dest = 0xf8f280 <donothingDR>, params = 0x0, queryEnv = 0x0,
instrument_options = 0, tupDesc = 0x20909a8, estate = 0x207f898, planstate = 0x207fab0, already_executed = false,
totaltime = 0x0}
到此,相信大家对“PostgreSQL中用于初始化查询执行计划函数是哪个”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
--结束END--
本文标题: PostgreSQL中用于初始化查询执行计划函数是哪个
本文链接: https://lsjlt.com/news/64778.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-10-23
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0