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

Appearance settings

Commit 5b618e1

Browse filesBrowse files
committed
Minor refactor of nodeAgg.c.
* Separate calculation of hash value from the lookup. * Split build_hash_table() into two functions. * Change lookup_hash_entry() to return AggStatePerGroup. That's all the caller needed, anyway. These changes are to support the upcoming Disk-based Hash Aggregation work. Discussion: https://postgr.es/m/31f5ab871a3ad5a1a91a7a797651f20e77ac7ce3.camel%40j-davis.com
1 parent 8021985 commit 5b618e1
Copy full SHA for 5b618e1

File tree

Expand file treeCollapse file tree

1 file changed

+89
-51
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+89
-51
lines changed

‎src/backend/executor/nodeAgg.c

Copy file name to clipboardExpand all lines: src/backend/executor/nodeAgg.c
+89-51Lines changed: 89 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ static void finalize_partialaggregate(AggState *aggstate,
263263
AggStatePerAgg peragg,
264264
AggStatePerGroup pergroupstate,
265265
Datum *resultVal, bool *resultIsNull);
266+
static void prepare_hash_slot(AggState *aggstate);
266267
static void prepare_projection_slot(AggState *aggstate,
267268
TupleTableSlot *slot,
268269
int currentSet);
@@ -272,8 +273,9 @@ static void finalize_aggregates(AggState *aggstate,
272273
static TupleTableSlot *project_aggregates(AggState *aggstate);
273274
static Bitmapset *find_unaggregated_cols(AggState *aggstate);
274275
static bool find_unaggregated_cols_walker(Node *node, Bitmapset **colnos);
275-
static void build_hash_table(AggState *aggstate);
276-
static TupleHashEntryData *lookup_hash_entry(AggState *aggstate);
276+
static void build_hash_tables(AggState *aggstate);
277+
static void build_hash_table(AggState *aggstate, int setno, long nbuckets);
278+
static AggStatePerGroup lookup_hash_entry(AggState *aggstate, uint32 hash);
277279
static void lookup_hash_entries(AggState *aggstate);
278280
static TupleTableSlot *agg_retrieve_direct(AggState *aggstate);
279281
static void agg_fill_hash_table(AggState *aggstate);
@@ -1035,6 +1037,32 @@ finalize_partialaggregate(AggState *aggstate,
10351037
MemoryContextSwitchTo(oldContext);
10361038
}
10371039

1040+
/*
1041+
* Extract the attributes that make up the grouping key into the
1042+
* hashslot. This is necessary to compute the hash or perform a lookup.
1043+
*/
1044+
static void
1045+
prepare_hash_slot(AggState *aggstate)
1046+
{
1047+
TupleTableSlot *inputslot = aggstate->tmpcontext->ecxt_outertuple;
1048+
AggStatePerHash perhash = &aggstate->perhash[aggstate->current_set];
1049+
TupleTableSlot *hashslot = perhash->hashslot;
1050+
int i;
1051+
1052+
/* transfer just the needed columns into hashslot */
1053+
slot_getsomeattrs(inputslot, perhash->largestGrpColIdx);
1054+
ExecClearTuple(hashslot);
1055+
1056+
for (i = 0; i < perhash->numhashGrpCols; i++)
1057+
{
1058+
int varNumber = perhash->hashGrpColIdxInput[i] - 1;
1059+
1060+
hashslot->tts_values[i] = inputslot->tts_values[varNumber];
1061+
hashslot->tts_isnull[i] = inputslot->tts_isnull[varNumber];
1062+
}
1063+
ExecStoreVirtualTuple(hashslot);
1064+
}
1065+
10381066
/*
10391067
* Prepare to finalize and project based on the specified representative tuple
10401068
* slot and grouping set.
@@ -1249,41 +1277,59 @@ find_unaggregated_cols_walker(Node *node, Bitmapset **colnos)
12491277
* they are all reset at the same time).
12501278
*/
12511279
static void
1252-
build_hash_table(AggState *aggstate)
1280+
build_hash_tables(AggState *aggstate)
12531281
{
1254-
MemoryContext tmpmem = aggstate->tmpcontext->ecxt_per_tuple_memory;
1255-
Size additionalsize;
1256-
int i;
1282+
int setno;
12571283

1258-
Assert(aggstate->aggstrategy == AGG_HASHED || aggstate->aggstrategy == AGG_MIXED);
1259-
1260-
additionalsize = aggstate->numtrans * sizeof(AggStatePerGroupData);
1261-
1262-
for (i = 0; i < aggstate->num_hashes; ++i)
1284+
for (setno = 0; setno < aggstate->num_hashes; ++setno)
12631285
{
1264-
AggStatePerHash perhash = &aggstate->perhash[i];
1286+
AggStatePerHash perhash = &aggstate->perhash[setno];
12651287

12661288
Assert(perhash->aggnode->numGroups > 0);
12671289

1268-
if (perhash->hashtable)
1269-
ResetTupleHashTable(perhash->hashtable);
1270-
else
1271-
perhash->hashtable = BuildTupleHashTableExt(&aggstate->ss.ps,
1272-
perhash->hashslot->tts_tupleDescriptor,
1273-
perhash->numCols,
1274-
perhash->hashGrpColIdxHash,
1275-
perhash->eqfuncoids,
1276-
perhash->hashfunctions,
1277-
perhash->aggnode->grpCollations,
1278-
perhash->aggnode->numGroups,
1279-
additionalsize,
1280-
aggstate->ss.ps.state->es_query_cxt,
1281-
aggstate->hashcontext->ecxt_per_tuple_memory,
1282-
tmpmem,
1283-
DO_AGGSPLIT_SKIPFINAL(aggstate->aggsplit));
1290+
build_hash_table(aggstate, setno, perhash->aggnode->numGroups);
12841291
}
12851292
}
12861293

1294+
/*
1295+
* Build a single hashtable for this grouping set.
1296+
*/
1297+
static void
1298+
build_hash_table(AggState *aggstate, int setno, long nbuckets)
1299+
{
1300+
AggStatePerHash perhash = &aggstate->perhash[setno];
1301+
MemoryContext metacxt = aggstate->ss.ps.state->es_query_cxt;
1302+
MemoryContext hashcxt = aggstate->hashcontext->ecxt_per_tuple_memory;
1303+
MemoryContext tmpcxt = aggstate->tmpcontext->ecxt_per_tuple_memory;
1304+
Size additionalsize;
1305+
1306+
Assert(aggstate->aggstrategy == AGG_HASHED ||
1307+
aggstate->aggstrategy == AGG_MIXED);
1308+
1309+
/*
1310+
* Used to make sure initial hash table allocation does not exceed
1311+
* work_mem. Note that the estimate does not include space for
1312+
* pass-by-reference transition data values, nor for the representative
1313+
* tuple of each group.
1314+
*/
1315+
additionalsize = aggstate->numtrans * sizeof(AggStatePerGroupData);
1316+
1317+
perhash->hashtable = BuildTupleHashTableExt(
1318+
&aggstate->ss.ps,
1319+
perhash->hashslot->tts_tupleDescriptor,
1320+
perhash->numCols,
1321+
perhash->hashGrpColIdxHash,
1322+
perhash->eqfuncoids,
1323+
perhash->hashfunctions,
1324+
perhash->aggnode->grpCollations,
1325+
nbuckets,
1326+
additionalsize,
1327+
metacxt,
1328+
hashcxt,
1329+
tmpcxt,
1330+
DO_AGGSPLIT_SKIPFINAL(aggstate->aggsplit));
1331+
}
1332+
12871333
/*
12881334
* Compute columns that actually need to be stored in hashtable entries. The
12891335
* incoming tuples from the child plan node will contain grouping columns,
@@ -1441,33 +1487,20 @@ hash_agg_entry_size(int numAggs, Size tupleWidth, Size transitionSpace)
14411487
* set (which the caller must have selected - note that initialize_aggregate
14421488
* depends on this).
14431489
*
1444-
* When called, CurrentMemoryContext should be the per-query context.
1490+
* When called, CurrentMemoryContext should be the per-query context. The
1491+
* already-calculated hash value for the tuple must be specified.
14451492
*/
1446-
static TupleHashEntryData *
1447-
lookup_hash_entry(AggState *aggstate)
1493+
static AggStatePerGroup
1494+
lookup_hash_entry(AggState *aggstate, uint32 hash)
14481495
{
1449-
TupleTableSlot *inputslot = aggstate->tmpcontext->ecxt_outertuple;
14501496
AggStatePerHash perhash = &aggstate->perhash[aggstate->current_set];
14511497
TupleTableSlot *hashslot = perhash->hashslot;
14521498
TupleHashEntryData *entry;
14531499
bool isnew;
1454-
int i;
1455-
1456-
/* transfer just the needed columns into hashslot */
1457-
slot_getsomeattrs(inputslot, perhash->largestGrpColIdx);
1458-
ExecClearTuple(hashslot);
1459-
1460-
for (i = 0; i < perhash->numhashGrpCols; i++)
1461-
{
1462-
int varNumber = perhash->hashGrpColIdxInput[i] - 1;
1463-
1464-
hashslot->tts_values[i] = inputslot->tts_values[varNumber];
1465-
hashslot->tts_isnull[i] = inputslot->tts_isnull[varNumber];
1466-
}
1467-
ExecStoreVirtualTuple(hashslot);
14681500

14691501
/* find or create the hashtable entry using the filtered tuple */
1470-
entry = LookupTupleHashEntry(perhash->hashtable, hashslot, &isnew);
1502+
entry = LookupTupleHashEntryHash(perhash->hashtable, hashslot, &isnew,
1503+
hash);
14711504

14721505
if (isnew)
14731506
{
@@ -1492,7 +1525,7 @@ lookup_hash_entry(AggState *aggstate)
14921525
}
14931526
}
14941527

1495-
return entry;
1528+
return entry->additional;
14961529
}
14971530

14981531
/*
@@ -1510,8 +1543,13 @@ lookup_hash_entries(AggState *aggstate)
15101543

15111544
for (setno = 0; setno < numHashes; setno++)
15121545
{
1546+
AggStatePerHash perhash = &aggstate->perhash[setno];
1547+
uint32 hash;
1548+
15131549
select_current_set(aggstate, setno, true);
1514-
pergroup[setno] = lookup_hash_entry(aggstate)->additional;
1550+
prepare_hash_slot(aggstate);
1551+
hash = TupleHashTableHash(perhash->hashtable, perhash->hashslot);
1552+
pergroup[setno] = lookup_hash_entry(aggstate, hash);
15151553
}
15161554
}
15171555

@@ -2478,7 +2516,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
24782516
aggstate->hash_pergroup = pergroups;
24792517

24802518
find_hash_columns(aggstate);
2481-
build_hash_table(aggstate);
2519+
build_hash_tables(aggstate);
24822520
aggstate->table_filled = false;
24832521
}
24842522

@@ -3498,7 +3536,7 @@ ExecReScanAgg(AggState *node)
34983536
{
34993537
ReScanExprContext(node->hashcontext);
35003538
/* Rebuild an empty hash table */
3501-
build_hash_table(node);
3539+
build_hash_tables(node);
35023540
node->table_filled = false;
35033541
/* iterator will be reset when the table is filled */
35043542
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.