1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-05 07:21:24 +03:00

Do execGrouping.c via expression eval machinery.

This has a performance benefit on own, although not hugely so. The
primary benefit is that it will allow for to JIT tuple deforming and
comparator invocations.

Author: Andres Freund
Discussion: https://postgr.es/m/20171129080934.amqqkke2zjtekd4t@alap3.anarazel.de
This commit is contained in:
Andres Freund
2018-02-15 21:55:31 -08:00
parent 51db0d18fb
commit 773aec7aa9
15 changed files with 498 additions and 366 deletions

View File

@ -755,7 +755,7 @@ process_ordered_aggregate_single(AggState *aggstate,
((oldIsNull && *isNull) ||
(!oldIsNull && !*isNull &&
oldAbbrevVal == newAbbrevVal &&
DatumGetBool(FunctionCall2(&pertrans->equalfns[0],
DatumGetBool(FunctionCall2(&pertrans->equalfnOne,
oldVal, *newVal)))))
{
/* equal to prior, so forget this one */
@ -802,7 +802,7 @@ process_ordered_aggregate_multi(AggState *aggstate,
AggStatePerTrans pertrans,
AggStatePerGroup pergroupstate)
{
MemoryContext workcontext = aggstate->tmpcontext->ecxt_per_tuple_memory;
ExprContext *tmpcontext = aggstate->tmpcontext;
FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo;
TupleTableSlot *slot1 = pertrans->sortslot;
TupleTableSlot *slot2 = pertrans->uniqslot;
@ -811,6 +811,7 @@ process_ordered_aggregate_multi(AggState *aggstate,
Datum newAbbrevVal = (Datum) 0;
Datum oldAbbrevVal = (Datum) 0;
bool haveOldValue = false;
TupleTableSlot *save = aggstate->tmpcontext->ecxt_outertuple;
int i;
tuplesort_performsort(pertrans->sortstates[aggstate->current_set]);
@ -824,22 +825,20 @@ process_ordered_aggregate_multi(AggState *aggstate,
{
CHECK_FOR_INTERRUPTS();
/*
* Extract the first numTransInputs columns as datums to pass to the
* transfn. (This will help execTuplesMatch too, so we do it
* immediately.)
*/
slot_getsomeattrs(slot1, numTransInputs);
tmpcontext->ecxt_outertuple = slot1;
tmpcontext->ecxt_innertuple = slot2;
if (numDistinctCols == 0 ||
!haveOldValue ||
newAbbrevVal != oldAbbrevVal ||
!execTuplesMatch(slot1, slot2,
numDistinctCols,
pertrans->sortColIdx,
pertrans->equalfns,
workcontext))
!ExecQual(pertrans->equalfnMulti, tmpcontext))
{
/*
* Extract the first numTransInputs columns as datums to pass to
* the transfn.
*/
slot_getsomeattrs(slot1, numTransInputs);
/* Load values into fcinfo */
/* Start from 1, since the 0th arg will be the transition value */
for (i = 0; i < numTransInputs; i++)
@ -857,15 +856,14 @@ process_ordered_aggregate_multi(AggState *aggstate,
slot2 = slot1;
slot1 = tmpslot;
/* avoid execTuplesMatch() calls by reusing abbreviated keys */
/* avoid ExecQual() calls by reusing abbreviated keys */
oldAbbrevVal = newAbbrevVal;
haveOldValue = true;
}
}
/* Reset context each time, unless execTuplesMatch did it for us */
if (numDistinctCols == 0)
MemoryContextReset(workcontext);
/* Reset context each time */
ResetExprContext(tmpcontext);
ExecClearTuple(slot1);
}
@ -875,6 +873,9 @@ process_ordered_aggregate_multi(AggState *aggstate,
tuplesort_end(pertrans->sortstates[aggstate->current_set]);
pertrans->sortstates[aggstate->current_set] = NULL;
/* restore previous slot, potentially in use for grouping sets */
tmpcontext->ecxt_outertuple = save;
}
/*
@ -1276,7 +1277,9 @@ build_hash_table(AggState *aggstate)
Assert(perhash->aggnode->numGroups > 0);
perhash->hashtable = BuildTupleHashTable(perhash->numCols,
perhash->hashtable = BuildTupleHashTable(&aggstate->ss.ps,
perhash->hashslot->tts_tupleDescriptor,
perhash->numCols,
perhash->hashGrpColIdxHash,
perhash->eqfunctions,
perhash->hashfunctions,
@ -1314,6 +1317,7 @@ find_hash_columns(AggState *aggstate)
Bitmapset *base_colnos;
List *outerTlist = outerPlanState(aggstate)->plan->targetlist;
int numHashes = aggstate->num_hashes;
EState *estate = aggstate->ss.ps.state;
int j;
/* Find Vars that will be needed in tlist and qual */
@ -1393,6 +1397,12 @@ find_hash_columns(AggState *aggstate)
}
hashDesc = ExecTypeFromTL(hashTlist, false);
execTuplesHashPrepare(perhash->numCols,
perhash->aggnode->grpOperators,
&perhash->eqfunctions,
&perhash->hashfunctions);
perhash->hashslot = ExecAllocTableSlot(&estate->es_tupleTable);
ExecSetSlotDescriptor(perhash->hashslot, hashDesc);
list_free(hashTlist);
@ -1694,17 +1704,14 @@ agg_retrieve_direct(AggState *aggstate)
* of the next grouping set
*----------
*/
tmpcontext->ecxt_innertuple = econtext->ecxt_outertuple;
if (aggstate->input_done ||
(node->aggstrategy != AGG_PLAIN &&
aggstate->projected_set != -1 &&
aggstate->projected_set < (numGroupingSets - 1) &&
nextSetSize > 0 &&
!execTuplesMatch(econtext->ecxt_outertuple,
tmpcontext->ecxt_outertuple,
nextSetSize,
node->grpColIdx,
aggstate->phase->eqfunctions,
tmpcontext->ecxt_per_tuple_memory)))
!ExecQualAndReset(aggstate->phase->eqfunctions[nextSetSize - 1],
tmpcontext)))
{
aggstate->projected_set += 1;
@ -1847,12 +1854,9 @@ agg_retrieve_direct(AggState *aggstate)
*/
if (node->aggstrategy != AGG_PLAIN)
{
if (!execTuplesMatch(firstSlot,
outerslot,
node->numCols,
node->grpColIdx,
aggstate->phase->eqfunctions,
tmpcontext->ecxt_per_tuple_memory))
tmpcontext->ecxt_innertuple = firstSlot;
if (!ExecQual(aggstate->phase->eqfunctions[node->numCols - 1],
tmpcontext))
{
aggstate->grp_firstTuple = ExecCopySlotTuple(outerslot);
break;
@ -2078,6 +2082,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
AggStatePerGroup *pergroups;
Plan *outerPlan;
ExprContext *econtext;
TupleDesc scanDesc;
int numaggs,
transno,
aggno;
@ -2233,9 +2238,9 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
* initialize source tuple type.
*/
ExecAssignScanTypeFromOuterPlan(&aggstate->ss);
scanDesc = aggstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
if (node->chain)
ExecSetSlotDescriptor(aggstate->sort_slot,
aggstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor);
ExecSetSlotDescriptor(aggstate->sort_slot, scanDesc);
/*
* Initialize result tuple type and projection info.
@ -2355,11 +2360,43 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
*/
if (aggnode->aggstrategy == AGG_SORTED)
{
int i = 0;
Assert(aggnode->numCols > 0);
/*
* Build a separate function for each subset of columns that
* need to be compared.
*/
phasedata->eqfunctions =
execTuplesMatchPrepare(aggnode->numCols,
aggnode->grpOperators);
(ExprState **) palloc0(aggnode->numCols * sizeof(ExprState *));
/* for each grouping set */
for (i = 0; i < phasedata->numsets; i++)
{
int length = phasedata->gset_lengths[i];
if (phasedata->eqfunctions[length - 1] != NULL)
continue;
phasedata->eqfunctions[length - 1] =
execTuplesMatchPrepare(scanDesc,
length,
aggnode->grpColIdx,
aggnode->grpOperators,
(PlanState *) aggstate);
}
/* and for all grouped columns, unless already computed */
if (phasedata->eqfunctions[aggnode->numCols - 1] == NULL)
{
phasedata->eqfunctions[aggnode->numCols - 1] =
execTuplesMatchPrepare(scanDesc,
aggnode->numCols,
aggnode->grpColIdx,
aggnode->grpOperators,
(PlanState *) aggstate);
}
}
phasedata->aggnode = aggnode;
@ -2412,16 +2449,6 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
*/
if (use_hashing)
{
for (i = 0; i < numHashes; ++i)
{
aggstate->perhash[i].hashslot = ExecInitExtraTupleSlot(estate);
execTuplesHashPrepare(aggstate->perhash[i].numCols,
aggstate->perhash[i].aggnode->grpOperators,
&aggstate->perhash[i].eqfunctions,
&aggstate->perhash[i].hashfunctions);
}
/* this is an array of pointers, not structures */
aggstate->hash_pergroup = pergroups;
@ -3101,24 +3128,28 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
if (aggref->aggdistinct)
{
Assert(numArguments > 0);
Oid *ops;
/*
* We need the equal function for each DISTINCT comparison we will
* make.
*/
pertrans->equalfns =
(FmgrInfo *) palloc(numDistinctCols * sizeof(FmgrInfo));
Assert(numArguments > 0);
Assert(list_length(aggref->aggdistinct) == numDistinctCols);
ops = palloc(numDistinctCols * sizeof(Oid));
i = 0;
foreach(lc, aggref->aggdistinct)
{
SortGroupClause *sortcl = (SortGroupClause *) lfirst(lc);
ops[i++] = ((SortGroupClause *) lfirst(lc))->eqop;
fmgr_info(get_opcode(sortcl->eqop), &pertrans->equalfns[i]);
i++;
}
Assert(i == numDistinctCols);
/* lookup / build the necessary comparators */
if (numDistinctCols == 1)
fmgr_info(get_opcode(ops[0]), &pertrans->equalfnOne);
else
pertrans->equalfnMulti =
execTuplesMatchPrepare(pertrans->sortdesc,
numDistinctCols,
pertrans->sortColIdx,
ops,
&aggstate->ss.ps);
pfree(ops);
}
pertrans->sortstates = (Tuplesortstate **)