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

Commit8dcc8e3

Browse files
committed
Refactor ExecGetJunkAttribute to avoid searching for junk attributes
by name on each and every row processed. Profiling suggests this maybuy a percent or two for simple UPDATE scenarios, which isn't huge,but when it's so easy to get ...
1 parent406d028 commit8dcc8e3

File tree

4 files changed

+90
-54
lines changed

4 files changed

+90
-54
lines changed

‎src/backend/executor/execJunk.c

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/execJunk.c,v 1.54 2006/07/14 14:52:18 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/execJunk.c,v 1.55 2006/12/04 02:06:55 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -26,24 +26,25 @@
2626
* never make it out of the executor, i.e. they are never printed,
2727
* returned or stored on disk. Their only purpose in life is to
2828
* store some information useful only to the executor, mainly the values
29-
* of some system attributes like "ctid" or rule locks.
29+
* of system attributes like "ctid", or sort key columns that are not to
30+
* be output.
3031
*
3132
* The general idea is the following: A target list consists of a list of
3233
* TargetEntry nodes containing expressions. Each TargetEntry has a field
3334
* called 'resjunk'. If the value of this field is true then the
3435
* corresponding attribute is a "junk" attribute.
3536
*
36-
* When we initialize a plan we call'ExecInitJunkFilter' to create
37-
* and store the appropriate information in the'es_junkFilter' attribute of
37+
* When we initialize a plan we call ExecInitJunkFilter to create
38+
* and store the appropriate information in the es_junkFilter attribute of
3839
* EState.
3940
*
40-
* We then execute the plan ignoring the"resjunk" attributes.
41+
* We then execute the plan, treating the resjunk attributes like any others.
4142
*
4243
* Finally, when at the top level we get back a tuple, we can call
43-
* ExecGetJunkAttribute to retrieve thevalue of the junk attributes we
44-
* are interested in, and ExecFilterJunk or ExecRemoveJunk to remove all
45-
* the junk attributes from a tuple. This new "clean" tuple is then printed,
46-
* replaced, deleted or inserted.
44+
*ExecFindJunkAttribute/ExecGetJunkAttribute to retrieve thevalues of the
45+
*junk attributes weare interested in, and ExecFilterJunk or ExecRemoveJunk
46+
*to remove allthe junk attributes from a tuple. This new "clean" tuple is
47+
*then printed,replaced, deleted or inserted.
4748
*
4849
*-------------------------------------------------------------------------
4950
*/
@@ -201,26 +202,16 @@ ExecInitJunkFilterConversion(List *targetList,
201202
}
202203

203204
/*
204-
* ExecGetJunkAttribute
205-
*
206-
* Given a tuple (slot), the junk filter and a junk attribute's name,
207-
* extract & return the value and isNull flag of this attribute.
205+
* ExecFindJunkAttribute
208206
*
209-
* It returns false iff no junk attribute with such name was found.
207+
* Locate the specified junk attribute in the junk filter's targetlist,
208+
* and return its resno. Returns InvalidAttrNumber if not found.
210209
*/
211-
bool
212-
ExecGetJunkAttribute(JunkFilter*junkfilter,
213-
TupleTableSlot*slot,
214-
char*attrName,
215-
Datum*value,
216-
bool*isNull)
210+
AttrNumber
211+
ExecFindJunkAttribute(JunkFilter*junkfilter,constchar*attrName)
217212
{
218213
ListCell*t;
219214

220-
/*
221-
* Look in the junkfilter's target list for an attribute with the given
222-
* name
223-
*/
224215
foreach(t,junkfilter->jf_targetList)
225216
{
226217
TargetEntry*tle=lfirst(t);
@@ -229,13 +220,27 @@ ExecGetJunkAttribute(JunkFilter *junkfilter,
229220
(strcmp(tle->resname,attrName)==0))
230221
{
231222
/* We found it ! */
232-
*value=slot_getattr(slot,tle->resno,isNull);
233-
return true;
223+
returntle->resno;
234224
}
235225
}
236226

237-
/* Ooops! We couldn't find this attribute... */
238-
return false;
227+
returnInvalidAttrNumber;
228+
}
229+
230+
/*
231+
* ExecGetJunkAttribute
232+
*
233+
* Given a junk filter's input tuple (slot) and a junk attribute's number
234+
* previously found by ExecFindJunkAttribute, extract & return the value and
235+
* isNull flag of the attribute.
236+
*/
237+
Datum
238+
ExecGetJunkAttribute(TupleTableSlot*slot,AttrNumberattno,
239+
bool*isNull)
240+
{
241+
Assert(attno>0);
242+
243+
returnslot_getattr(slot,attno,isNull);
239244
}
240245

241246
/*

‎src/backend/executor/execMain.c

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*
2727
*
2828
* IDENTIFICATION
29-
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.280 2006/10/0400:29:52 momjian Exp $
29+
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.281 2006/12/0402:06:55 tgl Exp $
3030
*
3131
*-------------------------------------------------------------------------
3232
*/
@@ -567,7 +567,9 @@ InitPlan(QueryDesc *queryDesc, int eflags)
567567
}
568568

569569
/*
570-
* Have to lock relations selected FOR UPDATE/FOR SHARE
570+
* Have to lock relations selected FOR UPDATE/FOR SHARE before we
571+
* initialize the plan tree, else we'd be doing a lock upgrade.
572+
* While we are at it, build the ExecRowMark list.
571573
*/
572574
estate->es_rowMarks=NIL;
573575
foreach(l,parseTree->rowMarks)
@@ -583,7 +585,8 @@ InitPlan(QueryDesc *queryDesc, int eflags)
583585
erm->rti=rc->rti;
584586
erm->forUpdate=rc->forUpdate;
585587
erm->noWait=rc->noWait;
586-
snprintf(erm->resname,sizeof(erm->resname),"ctid%u",rc->rti);
588+
/* We'll set up ctidAttno below */
589+
erm->ctidAttNo=InvalidAttrNumber;
587590
estate->es_rowMarks=lappend(estate->es_rowMarks,erm);
588591
}
589592

@@ -703,6 +706,16 @@ InitPlan(QueryDesc *queryDesc, int eflags)
703706
j=ExecInitJunkFilter(subplan->plan->targetlist,
704707
resultRelInfo->ri_RelationDesc->rd_att->tdhasoid,
705708
ExecAllocTableSlot(estate->es_tupleTable));
709+
/*
710+
* Since it must be UPDATE/DELETE, there had better be
711+
* a "ctid" junk attribute in the tlist ... but ctid could
712+
* be at a different resno for each result relation.
713+
* We look up the ctid resnos now and save them in the
714+
* junkfilters.
715+
*/
716+
j->jf_junkAttNo=ExecFindJunkAttribute(j,"ctid");
717+
if (!AttributeNumberIsValid(j->jf_junkAttNo))
718+
elog(ERROR,"could not find junk ctid column");
706719
resultRelInfo->ri_junkFilter=j;
707720
resultRelInfo++;
708721
}
@@ -726,9 +739,30 @@ InitPlan(QueryDesc *queryDesc, int eflags)
726739
if (estate->es_result_relation_info)
727740
estate->es_result_relation_info->ri_junkFilter=j;
728741

729-
/* For SELECT, want to return the cleaned tuple type */
730742
if (operation==CMD_SELECT)
743+
{
744+
/* For SELECT, want to return the cleaned tuple type */
731745
tupType=j->jf_cleanTupType;
746+
/* For SELECT FOR UPDATE/SHARE, find the ctid attrs now */
747+
foreach(l,estate->es_rowMarks)
748+
{
749+
ExecRowMark*erm= (ExecRowMark*)lfirst(l);
750+
charresname[32];
751+
752+
snprintf(resname,sizeof(resname),"ctid%u",erm->rti);
753+
erm->ctidAttNo=ExecFindJunkAttribute(j,resname);
754+
if (!AttributeNumberIsValid(erm->ctidAttNo))
755+
elog(ERROR,"could not find junk \"%s\" column",
756+
resname);
757+
}
758+
}
759+
elseif (operation==CMD_UPDATE||operation==CMD_DELETE)
760+
{
761+
/* For UPDATE/DELETE, find the ctid junk attr now */
762+
j->jf_junkAttNo=ExecFindJunkAttribute(j,"ctid");
763+
if (!AttributeNumberIsValid(j->jf_junkAttNo))
764+
elog(ERROR,"could not find junk ctid column");
765+
}
732766
}
733767
}
734768
else
@@ -1111,13 +1145,8 @@ lnext:;
11111145
*/
11121146
if (operation==CMD_UPDATE||operation==CMD_DELETE)
11131147
{
1114-
if (!ExecGetJunkAttribute(junkfilter,
1115-
slot,
1116-
"ctid",
1117-
&datum,
1118-
&isNull))
1119-
elog(ERROR,"could not find junk ctid column");
1120-
1148+
datum=ExecGetJunkAttribute(slot,junkfilter->jf_junkAttNo,
1149+
&isNull);
11211150
/* shouldn't ever get a null result... */
11221151
if (isNull)
11231152
elog(ERROR,"ctid is NULL");
@@ -1146,17 +1175,12 @@ lnext:;
11461175
LockTupleModelockmode;
11471176
HTSU_Resulttest;
11481177

1149-
if (!ExecGetJunkAttribute(junkfilter,
1150-
slot,
1151-
erm->resname,
1152-
&datum,
1153-
&isNull))
1154-
elog(ERROR,"could not find junk \"%s\" column",
1155-
erm->resname);
1156-
1178+
datum=ExecGetJunkAttribute(slot,
1179+
erm->ctidAttNo,
1180+
&isNull);
11571181
/* shouldn't ever get a null result... */
11581182
if (isNull)
1159-
elog(ERROR,"\"%s\" is NULL",erm->resname);
1183+
elog(ERROR,"ctid is NULL");
11601184

11611185
tuple.t_self=*((ItemPointer)DatumGetPointer(datum));
11621186

‎src/include/executor/executor.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.130 2006/10/0400:30:08 momjian Exp $
10+
* $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.131 2006/12/0402:06:55 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -110,8 +110,10 @@ extern JunkFilter *ExecInitJunkFilter(List *targetList, bool hasoid,
110110
externJunkFilter*ExecInitJunkFilterConversion(List*targetList,
111111
TupleDesccleanTupType,
112112
TupleTableSlot*slot);
113-
externboolExecGetJunkAttribute(JunkFilter*junkfilter,TupleTableSlot*slot,
114-
char*attrName,Datum*value,bool*isNull);
113+
externAttrNumberExecFindJunkAttribute(JunkFilter*junkfilter,
114+
constchar*attrName);
115+
externDatumExecGetJunkAttribute(TupleTableSlot*slot,AttrNumberattno,
116+
bool*isNull);
115117
externTupleTableSlot*ExecFilterJunk(JunkFilter*junkfilter,
116118
TupleTableSlot*slot);
117119
externHeapTupleExecRemoveJunk(JunkFilter*junkfilter,TupleTableSlot*slot);

‎src/include/nodes/execnodes.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.161 2006/09/28 20:51:42 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.162 2006/12/04 02:06:55 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -226,7 +226,8 @@ typedef struct ProjectionInfo
226226
* the tuple to be updated.This is needed to do the update, but we
227227
* don't want the ctid to be part of the stored new tuple! So, we
228228
* apply a "junk filter" to remove the junk attributes and form the
229-
* real output tuple.
229+
* real output tuple. The junkfilter code also provides routines to
230+
* extract the values of the junk attribute(s) from the input tuple.
230231
*
231232
* targetList:the original target list (including junk attributes).
232233
* cleanTupType:the tuple descriptor for the "clean" tuple (with
@@ -235,6 +236,9 @@ typedef struct ProjectionInfo
235236
*attribute numbers of the "original" tuple and the
236237
*attribute numbers of the "clean" tuple.
237238
* resultSlot:tuple slot used to hold cleaned tuple.
239+
* junkAttNo:not used by junkfilter code. Can be used by caller
240+
*to remember the attno of a specific junk attribute
241+
*(execMain.c stores the "ctid" attno here).
238242
* ----------------
239243
*/
240244
typedefstructJunkFilter
@@ -244,6 +248,7 @@ typedef struct JunkFilter
244248
TupleDescjf_cleanTupType;
245249
AttrNumber*jf_cleanMap;
246250
TupleTableSlot*jf_resultSlot;
251+
AttrNumberjf_junkAttNo;
247252
}JunkFilter;
248253

249254
/* ----------------
@@ -352,7 +357,7 @@ typedef struct ExecRowMark
352357
Indexrti;/* its range table index */
353358
boolforUpdate;/* true = FOR UPDATE, false = FOR SHARE */
354359
boolnoWait;/* NOWAIT option */
355-
charresname[32];/*name for its ctid junk attribute */
360+
AttrNumberctidAttNo;/*resno of its ctid junk attribute */
356361
}ExecRowMark;
357362

358363

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp