Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 85369f8

Browse files
committed
Refactor ExecProject and associated routines so that fast-path code is used
for simple Var targetlist entries all the time, even when there are other entries that are not simple Vars. Also, ensure that we prefetch attributes (with slot_getsomeattrs) for all Vars in the targetlist, even those buried within expressions. In combination these changes seem to significantly reduce the runtime for cases where tlists are mostly but not exclusively Vars. Per my proposal of yesterday.
1 parent 0e550ff commit 85369f8

File tree

3 files changed

+223
-152
lines changed

3 files changed

+223
-152
lines changed

src/backend/executor/execQual.c

+83-67
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.243 2009/03/27 18:30:21 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.244 2009/04/02 22:39:29 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -4966,6 +4966,7 @@ ExecCleanTargetListLength(List *targetlist)
49664966
* prepared to deal with sets of result tuples. Otherwise, a return
49674967
* of *isDone = ExprMultipleResult signifies a set element, and a return
49684968
* of *isDone = ExprEndResult signifies end of the set of tuple.
4969+
* We assume that *isDone has been initialized to ExprSingleResult by caller.
49694970
*/
49704971
static bool
49714972
ExecTargetList(List *targetlist,
@@ -4987,9 +4988,6 @@ ExecTargetList(List *targetlist,
49874988
/*
49884989
* evaluate all the expressions in the target list
49894990
*/
4990-
if (isDone)
4991-
*isDone = ExprSingleResult; /* until proven otherwise */
4992-
49934991
haveDoneSets = false; /* any exhausted set exprs in tlist? */
49944992

49954993
foreach(tl, targetlist)
@@ -5104,50 +5102,6 @@ ExecTargetList(List *targetlist,
51045102
return true;
51055103
}
51065104

5107-
/*
5108-
* ExecVariableList
5109-
* Evaluates a simple-Variable-list projection.
5110-
*
5111-
* Results are stored into the passed values and isnull arrays.
5112-
*/
5113-
static void
5114-
ExecVariableList(ProjectionInfo *projInfo,
5115-
Datum *values,
5116-
bool *isnull)
5117-
{
5118-
ExprContext *econtext = projInfo->pi_exprContext;
5119-
int *varSlotOffsets = projInfo->pi_varSlotOffsets;
5120-
int *varNumbers = projInfo->pi_varNumbers;
5121-
int i;
5122-
5123-
/*
5124-
* Force extraction of all input values that we need.
5125-
*/
5126-
if (projInfo->pi_lastInnerVar > 0)
5127-
slot_getsomeattrs(econtext->ecxt_innertuple,
5128-
projInfo->pi_lastInnerVar);
5129-
if (projInfo->pi_lastOuterVar > 0)
5130-
slot_getsomeattrs(econtext->ecxt_outertuple,
5131-
projInfo->pi_lastOuterVar);
5132-
if (projInfo->pi_lastScanVar > 0)
5133-
slot_getsomeattrs(econtext->ecxt_scantuple,
5134-
projInfo->pi_lastScanVar);
5135-
5136-
/*
5137-
* Assign to result by direct extraction of fields from source slots ... a
5138-
* mite ugly, but fast ...
5139-
*/
5140-
for (i = list_length(projInfo->pi_targetlist) - 1; i >= 0; i--)
5141-
{
5142-
char *slotptr = ((char *) econtext) + varSlotOffsets[i];
5143-
TupleTableSlot *varSlot = *((TupleTableSlot **) slotptr);
5144-
int varNumber = varNumbers[i] - 1;
5145-
5146-
values[i] = varSlot->tts_values[varNumber];
5147-
isnull[i] = varSlot->tts_isnull[varNumber];
5148-
}
5149-
}
5150-
51515105
/*
51525106
* ExecProject
51535107
*
@@ -5165,6 +5119,8 @@ TupleTableSlot *
51655119
ExecProject(ProjectionInfo *projInfo, ExprDoneCond *isDone)
51665120
{
51675121
TupleTableSlot *slot;
5122+
ExprContext *econtext;
5123+
int numSimpleVars;
51685124

51695125
/*
51705126
* sanity checks
@@ -5175,6 +5131,11 @@ ExecProject(ProjectionInfo *projInfo, ExprDoneCond *isDone)
51755131
* get the projection info we want
51765132
*/
51775133
slot = projInfo->pi_slot;
5134+
econtext = projInfo->pi_exprContext;
5135+
5136+
/* Assume single result row until proven otherwise */
5137+
if (isDone)
5138+
*isDone = ExprSingleResult;
51785139

51795140
/*
51805141
* Clear any former contents of the result slot. This makes it safe for
@@ -5184,29 +5145,84 @@ ExecProject(ProjectionInfo *projInfo, ExprDoneCond *isDone)
51845145
ExecClearTuple(slot);
51855146

51865147
/*
5187-
* form a new result tuple (if possible); if successful, mark the result
5188-
* slot as containing a valid virtual tuple
5148+
* Force extraction of all input values that we'll need. The
5149+
* Var-extraction loops below depend on this, and we are also prefetching
5150+
* all attributes that will be referenced in the generic expressions.
5151+
*/
5152+
if (projInfo->pi_lastInnerVar > 0)
5153+
slot_getsomeattrs(econtext->ecxt_innertuple,
5154+
projInfo->pi_lastInnerVar);
5155+
if (projInfo->pi_lastOuterVar > 0)
5156+
slot_getsomeattrs(econtext->ecxt_outertuple,
5157+
projInfo->pi_lastOuterVar);
5158+
if (projInfo->pi_lastScanVar > 0)
5159+
slot_getsomeattrs(econtext->ecxt_scantuple,
5160+
projInfo->pi_lastScanVar);
5161+
5162+
/*
5163+
* Assign simple Vars to result by direct extraction of fields from source
5164+
* slots ... a mite ugly, but fast ...
51895165
*/
5190-
if (projInfo->pi_isVarList)
5166+
numSimpleVars = projInfo->pi_numSimpleVars;
5167+
if (numSimpleVars > 0)
51915168
{
5192-
/* simple Var list: this always succeeds with one result row */
5193-
if (isDone)
5194-
*isDone = ExprSingleResult;
5195-
ExecVariableList(projInfo,
5196-
slot->tts_values,
5197-
slot->tts_isnull);
5198-
ExecStoreVirtualTuple(slot);
5169+
Datum *values = slot->tts_values;
5170+
bool *isnull = slot->tts_isnull;
5171+
int *varSlotOffsets = projInfo->pi_varSlotOffsets;
5172+
int *varNumbers = projInfo->pi_varNumbers;
5173+
int i;
5174+
5175+
if (projInfo->pi_directMap)
5176+
{
5177+
/* especially simple case where vars go to output in order */
5178+
for (i = 0; i < numSimpleVars; i++)
5179+
{
5180+
char *slotptr = ((char *) econtext) + varSlotOffsets[i];
5181+
TupleTableSlot *varSlot = *((TupleTableSlot **) slotptr);
5182+
int varNumber = varNumbers[i] - 1;
5183+
5184+
values[i] = varSlot->tts_values[varNumber];
5185+
isnull[i] = varSlot->tts_isnull[varNumber];
5186+
}
5187+
}
5188+
else
5189+
{
5190+
/* we have to pay attention to varOutputCols[] */
5191+
int *varOutputCols = projInfo->pi_varOutputCols;
5192+
5193+
for (i = 0; i < numSimpleVars; i++)
5194+
{
5195+
char *slotptr = ((char *) econtext) + varSlotOffsets[i];
5196+
TupleTableSlot *varSlot = *((TupleTableSlot **) slotptr);
5197+
int varNumber = varNumbers[i] - 1;
5198+
int varOutputCol = varOutputCols[i] - 1;
5199+
5200+
values[varOutputCol] = varSlot->tts_values[varNumber];
5201+
isnull[varOutputCol] = varSlot->tts_isnull[varNumber];
5202+
}
5203+
}
51995204
}
5200-
else
5205+
5206+
/*
5207+
* If there are any generic expressions, evaluate them. It's possible
5208+
* that there are set-returning functions in such expressions; if so
5209+
* and we have reached the end of the set, we return the result slot,
5210+
* which we already marked empty.
5211+
*/
5212+
if (projInfo->pi_targetlist)
52015213
{
5202-
if (ExecTargetList(projInfo->pi_targetlist,
5203-
projInfo->pi_exprContext,
5204-
slot->tts_values,
5205-
slot->tts_isnull,
5206-
projInfo->pi_itemIsDone,
5207-
isDone))
5208-
ExecStoreVirtualTuple(slot);
5214+
if (!ExecTargetList(projInfo->pi_targetlist,
5215+
econtext,
5216+
slot->tts_values,
5217+
slot->tts_isnull,
5218+
projInfo->pi_itemIsDone,
5219+
isDone))
5220+
return slot; /* no more result rows, return empty slot */
52095221
}
52105222

5211-
return slot;
5223+
/*
5224+
* Successfully formed a result row. Mark the result slot as containing a
5225+
* valid virtual tuple.
5226+
*/
5227+
return ExecStoreVirtualTuple(slot);
52125228
}

0 commit comments

Comments
 (0)