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

Commit4cff59d

Browse files
committed
Tweak planner and executor to avoid doing ExecProject() in table scan
nodes where it's not really necessary. In many cases where the scan nodeis not the topmost plan node (eg, joins, aggregation), it's possible tojust return the table tuple directly instead of generating an intermediateprojection tuple. In preliminary testing, this reduced the CPU timeneeded for 'SELECT COUNT(*) FROM foo' by about 10%.
1 parent0d3e36b commit4cff59d

File tree

12 files changed

+462
-216
lines changed

12 files changed

+462
-216
lines changed

‎src/backend/executor/execMain.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*
2727
*
2828
* IDENTIFICATION
29-
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.199 2003/01/23 05:10:37 tgl Exp $
29+
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.200 2003/02/03 15:07:06 tgl Exp $
3030
*
3131
*-------------------------------------------------------------------------
3232
*/
@@ -612,9 +612,11 @@ InitPlan(QueryDesc *queryDesc)
612612
tupType=ExecGetTupType(planstate);
613613

614614
/*
615-
* Initialize the junk filter if needed. SELECT and INSERT queries
616-
* need a filter if there are any junk attrs in the tlist.UPDATE and
617-
* DELETE always need one, since there's always a junk 'ctid'
615+
* Initialize the junk filter if needed. SELECT and INSERT queries need a
616+
* filter if there are any junk attrs in the tlist. INSERT and SELECT
617+
* INTO also need a filter if the top plan node is a scan node that's not
618+
* doing projection (else we'll be scribbling on the scan tuple!) UPDATE
619+
* and DELETE always need a filter, since there's always a junk 'ctid'
618620
* attribute present --- no need to look first.
619621
*/
620622
{
@@ -635,6 +637,19 @@ InitPlan(QueryDesc *queryDesc)
635637
break;
636638
}
637639
}
640+
if (!junk_filter_needed&&
641+
(operation==CMD_INSERT||do_select_into))
642+
{
643+
if (IsA(planstate,SeqScanState)||
644+
IsA(planstate,IndexScanState)||
645+
IsA(planstate,TidScanState)||
646+
IsA(planstate,SubqueryScanState)||
647+
IsA(planstate,FunctionScanState))
648+
{
649+
if (planstate->ps_ProjInfo==NULL)
650+
junk_filter_needed= true;
651+
}
652+
}
638653
break;
639654
caseCMD_UPDATE:
640655
caseCMD_DELETE:

‎src/backend/executor/execScan.c

Lines changed: 92 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,20 @@
1212
*
1313
*
1414
* IDENTIFICATION
15-
* $Header: /cvsroot/pgsql/src/backend/executor/execScan.c,v 1.22 2002/12/05 15:50:32 tgl Exp $
15+
* $Header: /cvsroot/pgsql/src/backend/executor/execScan.c,v 1.23 2003/02/03 15:07:07 tgl Exp $
1616
*
1717
*-------------------------------------------------------------------------
1818
*/
1919
#include"postgres.h"
2020

21-
#include<sys/file.h>
22-
2321
#include"executor/executor.h"
2422
#include"miscadmin.h"
2523
#include"utils/memutils.h"
2624

2725

26+
staticbooltlist_matches_tupdesc(List*tlist,Indexvarno,TupleDesctupdesc);
27+
28+
2829
/* ----------------------------------------------------------------
2930
*ExecScan
3031
*
@@ -50,6 +51,7 @@ ExecScan(ScanState *node,
5051
EState*estate;
5152
ExprContext*econtext;
5253
List*qual;
54+
ProjectionInfo*projInfo;
5355
ExprDoneCondisDone;
5456
TupleTableSlot*resultSlot;
5557

@@ -59,6 +61,7 @@ ExecScan(ScanState *node,
5961
estate=node->ps.state;
6062
econtext=node->ps.ps_ExprContext;
6163
qual=node->ps.qual;
64+
projInfo=node->ps.ps_ProjInfo;
6265

6366
/*
6467
* Check to see if we're still projecting out tuples from a previous
@@ -67,7 +70,8 @@ ExecScan(ScanState *node,
6770
*/
6871
if (node->ps.ps_TupFromTlist)
6972
{
70-
resultSlot=ExecProject(node->ps.ps_ProjInfo,&isDone);
73+
Assert(projInfo);/* can't get here if not projecting */
74+
resultSlot=ExecProject(projInfo,&isDone);
7175
if (isDone==ExprMultipleResult)
7276
returnresultSlot;
7377
/* Done with that source tuple... */
@@ -101,10 +105,13 @@ ExecScan(ScanState *node,
101105
*/
102106
if (TupIsNull(slot))
103107
{
104-
returnExecStoreTuple(NULL,
105-
node->ps.ps_ProjInfo->pi_slot,
106-
InvalidBuffer,
107-
true);
108+
if (projInfo)
109+
returnExecStoreTuple(NULL,
110+
projInfo->pi_slot,
111+
InvalidBuffer,
112+
true);
113+
else
114+
returnslot;
108115
}
109116

110117
/*
@@ -123,16 +130,27 @@ ExecScan(ScanState *node,
123130
{
124131
/*
125132
* Found a satisfactory scan tuple.
126-
*
127-
* Form a projection tuple, store it in the result tuple slot and
128-
* return it --- unless we find we can project no tuples from
129-
* this scan tuple, in which case continue scan.
130133
*/
131-
resultSlot=ExecProject(node->ps.ps_ProjInfo,&isDone);
132-
if (isDone!=ExprEndResult)
134+
if (projInfo)
133135
{
134-
node->ps.ps_TupFromTlist= (isDone==ExprMultipleResult);
135-
returnresultSlot;
136+
/*
137+
* Form a projection tuple, store it in the result tuple slot
138+
* and return it --- unless we find we can project no tuples
139+
* from this scan tuple, in which case continue scan.
140+
*/
141+
resultSlot=ExecProject(projInfo,&isDone);
142+
if (isDone!=ExprEndResult)
143+
{
144+
node->ps.ps_TupFromTlist= (isDone==ExprMultipleResult);
145+
returnresultSlot;
146+
}
147+
}
148+
else
149+
{
150+
/*
151+
* Here, we aren't projecting, so just return scan tuple.
152+
*/
153+
returnslot;
136154
}
137155
}
138156

@@ -142,3 +160,61 @@ ExecScan(ScanState *node,
142160
ResetExprContext(econtext);
143161
}
144162
}
163+
164+
/*
165+
* ExecAssignScanProjectionInfo
166+
*Set up projection info for a scan node, if necessary.
167+
*
168+
* We can avoid a projection step if the requested tlist exactly matches
169+
* the underlying tuple type. If so, we just set ps_ProjInfo to NULL.
170+
* Note that this case occurs not only for simple "SELECT * FROM ...", but
171+
* also in most cases where there are joins or other processing nodes above
172+
* the scan node, because the planner will preferentially generate a matching
173+
* tlist.
174+
*
175+
* ExecAssignScanType must have been called already.
176+
*/
177+
void
178+
ExecAssignScanProjectionInfo(ScanState*node)
179+
{
180+
Scan*scan= (Scan*)node->ps.plan;
181+
182+
if (tlist_matches_tupdesc(scan->plan.targetlist,
183+
scan->scanrelid,
184+
node->ss_ScanTupleSlot->ttc_tupleDescriptor))
185+
node->ps.ps_ProjInfo=NULL;
186+
else
187+
ExecAssignProjectionInfo(&node->ps);
188+
}
189+
190+
staticbool
191+
tlist_matches_tupdesc(List*tlist,Indexvarno,TupleDesctupdesc)
192+
{
193+
intnumattrs=tupdesc->natts;
194+
intattrno;
195+
196+
for (attrno=1;attrno <=numattrs;attrno++)
197+
{
198+
Form_pg_attributeatt_tup=tupdesc->attrs[attrno-1];
199+
Var*var;
200+
201+
if (tlist==NIL)
202+
return false;/* tlist too short */
203+
var= (Var*) ((TargetEntry*)lfirst(tlist))->expr;
204+
if (!var|| !IsA(var,Var))
205+
return false;/* tlist item not a Var */
206+
Assert(var->varno==varno);
207+
if (var->varattno!=attrno)
208+
return false;/* out of order */
209+
Assert(var->vartype==att_tup->atttypid);
210+
Assert(var->vartypmod==att_tup->atttypmod);
211+
Assert(var->varlevelsup==0);
212+
213+
tlist=lnext(tlist);
214+
}
215+
216+
if (tlist)
217+
return false;/* tlist too long */
218+
219+
return true;
220+
}

‎src/backend/executor/nodeIndexscan.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.77 2003/01/12 22:01:38 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.78 2003/02/03 15:07:07 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -582,12 +582,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
582582
ExecInitResultTupleSlot(estate,&indexstate->ss.ps);
583583
ExecInitScanTupleSlot(estate,&indexstate->ss);
584584

585-
/*
586-
* Initialize result tuple type and projection info.
587-
*/
588-
ExecAssignResultTypeFromTL(&indexstate->ss.ps);
589-
ExecAssignProjectionInfo(&indexstate->ss.ps);
590-
591585
/*
592586
* Initialize index-specific scan state
593587
*/
@@ -917,6 +911,12 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
917911
indexstate->iss_RelationDescs=indexDescs;
918912
indexstate->iss_ScanDescs=scanDescs;
919913

914+
/*
915+
* Initialize result tuple type and projection info.
916+
*/
917+
ExecAssignResultTypeFromTL(&indexstate->ss.ps);
918+
ExecAssignScanProjectionInfo(&indexstate->ss);
919+
920920
/*
921921
* all done.
922922
*/

‎src/backend/executor/nodeSeqscan.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.42 2003/01/12 22:01:38 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.43 2003/02/03 15:07:07 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -232,7 +232,7 @@ ExecInitSeqScan(SeqScan *node, EState *estate)
232232
* Initialize result tuple type and projection info.
233233
*/
234234
ExecAssignResultTypeFromTL(&scanstate->ps);
235-
ExecAssignProjectionInfo(&scanstate->ps);
235+
ExecAssignScanProjectionInfo(scanstate);
236236

237237
returnscanstate;
238238
}

‎src/backend/executor/nodeTidscan.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.31 2003/01/12 22:01:38 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.32 2003/02/03 15:07:07 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -383,12 +383,6 @@ ExecInitTidScan(TidScan *node, EState *estate)
383383
ExecInitResultTupleSlot(estate,&tidstate->ss.ps);
384384
ExecInitScanTupleSlot(estate,&tidstate->ss);
385385

386-
/*
387-
* Initialize result tuple type and projection info.
388-
*/
389-
ExecAssignResultTypeFromTL(&tidstate->ss.ps);
390-
ExecAssignProjectionInfo(&tidstate->ss.ps);
391-
392386
/*
393387
* get the tid node information
394388
*/
@@ -438,6 +432,12 @@ ExecInitTidScan(TidScan *node, EState *estate)
438432
*/
439433
tidstate->ss.ps.chgParam=execParam;
440434

435+
/*
436+
* Initialize result tuple type and projection info.
437+
*/
438+
ExecAssignResultTypeFromTL(&tidstate->ss.ps);
439+
ExecAssignScanProjectionInfo(&tidstate->ss);
440+
441441
/*
442442
* all done.
443443
*/

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp