Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb10967e

Browse files
committed
Avoid projecting tuples unnecessarily in Gather and Gather Merge.
It's most often the case that the target list for the Gather (Merge)node matches the target list supplied by the underlying plan node;when this is so, we can avoid the overhead of projecting.This depends on commitf455e11 forproper functioning.Idea by Andres Freund. Patch by me. Review by Amit Kapila.Discussion:http://postgr.es/m/CA+TgmoZ0ZL=cesZFq8c9NnfK6bqy-wwUd3_74iYGodYrSoQ7Fw@mail.gmail.com
1 parent0f2458f commitb10967e

File tree

5 files changed

+110
-87
lines changed

5 files changed

+110
-87
lines changed

‎src/backend/executor/execScan.c

Lines changed: 4 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@
2323
#include"utils/memutils.h"
2424

2525

26-
staticbooltlist_matches_tupdesc(PlanState*ps,List*tlist,Indexvarno,TupleDesctupdesc);
27-
2826

2927
/*
3028
* ExecScanFetch -- check interrupts & fetch next potential tuple
@@ -237,8 +235,9 @@ void
237235
ExecAssignScanProjectionInfo(ScanState*node)
238236
{
239237
Scan*scan= (Scan*)node->ps.plan;
238+
TupleDesctupdesc=node->ss_ScanTupleSlot->tts_tupleDescriptor;
240239

241-
ExecAssignScanProjectionInfoWithVarno(node,scan->scanrelid);
240+
ExecConditionalAssignProjectionInfo(&node->ps,tupdesc,scan->scanrelid);
242241
}
243242

244243
/*
@@ -248,75 +247,9 @@ ExecAssignScanProjectionInfo(ScanState *node)
248247
void
249248
ExecAssignScanProjectionInfoWithVarno(ScanState*node,Indexvarno)
250249
{
251-
Scan*scan= (Scan*)node->ps.plan;
252-
253-
if (tlist_matches_tupdesc(&node->ps,
254-
scan->plan.targetlist,
255-
varno,
256-
node->ss_ScanTupleSlot->tts_tupleDescriptor))
257-
node->ps.ps_ProjInfo=NULL;
258-
else
259-
ExecAssignProjectionInfo(&node->ps,
260-
node->ss_ScanTupleSlot->tts_tupleDescriptor);
261-
}
262-
263-
staticbool
264-
tlist_matches_tupdesc(PlanState*ps,List*tlist,Indexvarno,TupleDesctupdesc)
265-
{
266-
intnumattrs=tupdesc->natts;
267-
intattrno;
268-
boolhasoid;
269-
ListCell*tlist_item=list_head(tlist);
270-
271-
/* Check the tlist attributes */
272-
for (attrno=1;attrno <=numattrs;attrno++)
273-
{
274-
Form_pg_attributeatt_tup=TupleDescAttr(tupdesc,attrno-1);
275-
Var*var;
276-
277-
if (tlist_item==NULL)
278-
return false;/* tlist too short */
279-
var= (Var*) ((TargetEntry*)lfirst(tlist_item))->expr;
280-
if (!var|| !IsA(var,Var))
281-
return false;/* tlist item not a Var */
282-
/* if these Asserts fail, planner messed up */
283-
Assert(var->varno==varno);
284-
Assert(var->varlevelsup==0);
285-
if (var->varattno!=attrno)
286-
return false;/* out of order */
287-
if (att_tup->attisdropped)
288-
return false;/* table contains dropped columns */
289-
290-
/*
291-
* Note: usually the Var's type should match the tupdesc exactly, but
292-
* in situations involving unions of columns that have different
293-
* typmods, the Var may have come from above the union and hence have
294-
* typmod -1. This is a legitimate situation since the Var still
295-
* describes the column, just not as exactly as the tupdesc does. We
296-
* could change the planner to prevent it, but it'd then insert
297-
* projection steps just to convert from specific typmod to typmod -1,
298-
* which is pretty silly.
299-
*/
300-
if (var->vartype!=att_tup->atttypid||
301-
(var->vartypmod!=att_tup->atttypmod&&
302-
var->vartypmod!=-1))
303-
return false;/* type mismatch */
304-
305-
tlist_item=lnext(tlist_item);
306-
}
307-
308-
if (tlist_item)
309-
return false;/* tlist too long */
310-
311-
/*
312-
* If the plan context requires a particular hasoid setting, then that has
313-
* to match, too.
314-
*/
315-
if (ExecContextForcesOids(ps,&hasoid)&&
316-
hasoid!=tupdesc->tdhasoid)
317-
return false;
250+
TupleDesctupdesc=node->ss_ScanTupleSlot->tts_tupleDescriptor;
318251

319-
return true;
252+
ExecConditionalAssignProjectionInfo(&node->ps,tupdesc,varno);
320253
}
321254

322255
/*

‎src/backend/executor/execUtils.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
#include"utils/typcache.h"
5757

5858

59+
staticbooltlist_matches_tupdesc(PlanState*ps,List*tlist,Indexvarno,TupleDesctupdesc);
5960
staticvoidShutdownExprContext(ExprContext*econtext,boolisCommit);
6061

6162

@@ -503,6 +504,85 @@ ExecAssignProjectionInfo(PlanState *planstate,
503504
}
504505

505506

507+
/* ----------------
508+
*ExecConditionalAssignProjectionInfo
509+
*
510+
* as ExecAssignProjectionInfo, but store NULL rather than building projection
511+
* info if no projection is required
512+
* ----------------
513+
*/
514+
void
515+
ExecConditionalAssignProjectionInfo(PlanState*planstate,TupleDescinputDesc,
516+
Indexvarno)
517+
{
518+
if (tlist_matches_tupdesc(planstate,
519+
planstate->plan->targetlist,
520+
varno,
521+
inputDesc))
522+
planstate->ps_ProjInfo=NULL;
523+
else
524+
ExecAssignProjectionInfo(planstate,inputDesc);
525+
}
526+
527+
staticbool
528+
tlist_matches_tupdesc(PlanState*ps,List*tlist,Indexvarno,TupleDesctupdesc)
529+
{
530+
intnumattrs=tupdesc->natts;
531+
intattrno;
532+
boolhasoid;
533+
ListCell*tlist_item=list_head(tlist);
534+
535+
/* Check the tlist attributes */
536+
for (attrno=1;attrno <=numattrs;attrno++)
537+
{
538+
Form_pg_attributeatt_tup=TupleDescAttr(tupdesc,attrno-1);
539+
Var*var;
540+
541+
if (tlist_item==NULL)
542+
return false;/* tlist too short */
543+
var= (Var*) ((TargetEntry*)lfirst(tlist_item))->expr;
544+
if (!var|| !IsA(var,Var))
545+
return false;/* tlist item not a Var */
546+
/* if these Asserts fail, planner messed up */
547+
Assert(var->varno==varno);
548+
Assert(var->varlevelsup==0);
549+
if (var->varattno!=attrno)
550+
return false;/* out of order */
551+
if (att_tup->attisdropped)
552+
return false;/* table contains dropped columns */
553+
554+
/*
555+
* Note: usually the Var's type should match the tupdesc exactly, but
556+
* in situations involving unions of columns that have different
557+
* typmods, the Var may have come from above the union and hence have
558+
* typmod -1. This is a legitimate situation since the Var still
559+
* describes the column, just not as exactly as the tupdesc does. We
560+
* could change the planner to prevent it, but it'd then insert
561+
* projection steps just to convert from specific typmod to typmod -1,
562+
* which is pretty silly.
563+
*/
564+
if (var->vartype!=att_tup->atttypid||
565+
(var->vartypmod!=att_tup->atttypmod&&
566+
var->vartypmod!=-1))
567+
return false;/* type mismatch */
568+
569+
tlist_item=lnext(tlist_item);
570+
}
571+
572+
if (tlist_item)
573+
return false;/* tlist too long */
574+
575+
/*
576+
* If the plan context requires a particular hasoid setting, then that has
577+
* to match, too.
578+
*/
579+
if (ExecContextForcesOids(ps,&hasoid)&&
580+
hasoid!=tupdesc->tdhasoid)
581+
return false;
582+
583+
return true;
584+
}
585+
506586
/* ----------------
507587
*ExecFreeExprContext
508588
*

‎src/backend/executor/nodeGather.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,6 @@ ExecInitGather(Gather *node, EState *estate, int eflags)
103103
outerNode=outerPlan(node);
104104
outerPlanState(gatherstate)=ExecInitNode(outerNode,estate,eflags);
105105

106-
/*
107-
* Initialize result tuple type and projection info.
108-
*/
109-
ExecAssignResultTypeFromTL(&gatherstate->ps);
110-
ExecAssignProjectionInfo(&gatherstate->ps,NULL);
111-
112106
/*
113107
* Initialize funnel slot to same tuple descriptor as outer plan.
114108
*/
@@ -117,6 +111,12 @@ ExecInitGather(Gather *node, EState *estate, int eflags)
117111
tupDesc=ExecTypeFromTL(outerNode->targetlist,hasoid);
118112
ExecSetSlotDescriptor(gatherstate->funnel_slot,tupDesc);
119113

114+
/*
115+
* Initialize result tuple type and projection info.
116+
*/
117+
ExecAssignResultTypeFromTL(&gatherstate->ps);
118+
ExecConditionalAssignProjectionInfo(&gatherstate->ps,tupDesc,OUTER_VAR);
119+
120120
returngatherstate;
121121
}
122122

@@ -221,6 +221,10 @@ ExecGather(PlanState *pstate)
221221
if (TupIsNull(slot))
222222
returnNULL;
223223

224+
/* If no projection is required, we're done. */
225+
if (node->ps.ps_ProjInfo==NULL)
226+
returnslot;
227+
224228
/*
225229
* Form the result tuple using ExecProject(), and return it.
226230
*/

‎src/backend/executor/nodeGatherMerge.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,20 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags)
115115
outerNode=outerPlan(node);
116116
outerPlanState(gm_state)=ExecInitNode(outerNode,estate,eflags);
117117

118+
/*
119+
* Store the tuple descriptor into gather merge state, so we can use it
120+
* while initializing the gather merge slots.
121+
*/
122+
if (!ExecContextForcesOids(outerPlanState(gm_state),&hasoid))
123+
hasoid= false;
124+
tupDesc=ExecTypeFromTL(outerNode->targetlist,hasoid);
125+
gm_state->tupDesc=tupDesc;
126+
118127
/*
119128
* Initialize result tuple type and projection info.
120129
*/
121130
ExecAssignResultTypeFromTL(&gm_state->ps);
122-
ExecAssignProjectionInfo(&gm_state->ps,NULL);
131+
ExecConditionalAssignProjectionInfo(&gm_state->ps,tupDesc,OUTER_VAR);
123132

124133
/*
125134
* initialize sort-key information
@@ -151,15 +160,6 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags)
151160
}
152161
}
153162

154-
/*
155-
* Store the tuple descriptor into gather merge state, so we can use it
156-
* while initializing the gather merge slots.
157-
*/
158-
if (!ExecContextForcesOids(outerPlanState(gm_state),&hasoid))
159-
hasoid= false;
160-
tupDesc=ExecTypeFromTL(outerNode->targetlist,hasoid);
161-
gm_state->tupDesc=tupDesc;
162-
163163
/* Now allocate the workspace for gather merge */
164164
gather_merge_setup(gm_state);
165165

@@ -257,6 +257,10 @@ ExecGatherMerge(PlanState *pstate)
257257
if (TupIsNull(slot))
258258
returnNULL;
259259

260+
/* If no projection is required, we're done. */
261+
if (node->ps.ps_ProjInfo==NULL)
262+
returnslot;
263+
260264
/*
261265
* Form the result tuple using ExecProject(), and return it.
262266
*/

‎src/include/executor/executor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,8 @@ extern void ExecAssignResultTypeFromTL(PlanState *planstate);
485485
externTupleDescExecGetResultType(PlanState*planstate);
486486
externvoidExecAssignProjectionInfo(PlanState*planstate,
487487
TupleDescinputDesc);
488+
externvoidExecConditionalAssignProjectionInfo(PlanState*planstate,
489+
TupleDescinputDesc,Indexvarno);
488490
externvoidExecFreeExprContext(PlanState*planstate);
489491
externvoidExecAssignScanType(ScanState*scanstate,TupleDesctupDesc);
490492
externvoidExecAssignScanTypeFromOuterPlan(ScanState*scanstate);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp