diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/executor/execGrouping.c | 14 | ||||
-rw-r--r-- | src/backend/executor/nodeAgg.c | 32 | ||||
-rw-r--r-- | src/backend/executor/nodeSetOp.c | 33 | ||||
-rw-r--r-- | src/backend/executor/nodeSubplan.c | 2 | ||||
-rw-r--r-- | src/include/executor/executor.h | 34 | ||||
-rw-r--r-- | src/include/nodes/execnodes.h | 1 |
6 files changed, 83 insertions, 33 deletions
diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c index 33b124fbb0a..a9d212aaec6 100644 --- a/src/backend/executor/execGrouping.c +++ b/src/backend/executor/execGrouping.c @@ -174,13 +174,15 @@ BuildTupleHashTable(PlanState *parent, bool use_variable_hash_iv) { TupleHashTable hashtable; - Size entrysize = sizeof(TupleHashEntryData) + additionalsize; + Size entrysize; Size hash_mem_limit; MemoryContext oldcontext; bool allow_jit; uint32 hash_iv = 0; Assert(nbuckets > 0); + additionalsize = MAXALIGN(additionalsize); + entrysize = sizeof(TupleHashEntryData) + additionalsize; /* Limit initial table size request to not more than hash_mem */ hash_mem_limit = get_hash_memory_limit() / entrysize; @@ -196,6 +198,7 @@ BuildTupleHashTable(PlanState *parent, hashtable->tab_collations = collations; hashtable->tablecxt = tablecxt; hashtable->tempcxt = tempcxt; + hashtable->additionalsize = additionalsize; hashtable->tableslot = NULL; /* will be made on first lookup */ hashtable->inputslot = NULL; hashtable->in_hash_expr = NULL; @@ -479,11 +482,14 @@ LookupTupleHashEntry_internal(TupleHashTable hashtable, TupleTableSlot *slot, { /* created new entry */ *isnew = true; - /* zero caller data */ - entry->additional = NULL; + MemoryContextSwitchTo(hashtable->tablecxt); - /* Copy the first tuple into the table context */ + entry->firstTuple = ExecCopySlotMinimalTuple(slot); + if (hashtable->additionalsize > 0) + entry->additional = palloc0(hashtable->additionalsize); + else + entry->additional = NULL; } } else diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index beccbfdc6fe..f83fc16c5c8 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -1491,7 +1491,7 @@ build_hash_tables(AggState *aggstate) #ifdef USE_INJECTION_POINTS if (IS_INJECTION_POINT_ATTACHED("hash-aggregate-oversize-table")) { - nbuckets = memory / sizeof(TupleHashEntryData); + nbuckets = memory / TupleHashEntrySize(); INJECTION_POINT_CACHED("hash-aggregate-oversize-table"); } #endif @@ -1724,7 +1724,7 @@ hash_agg_entry_size(int numTrans, Size tupleWidth, Size transitionSpace) transitionChunkSize = 0; return - sizeof(TupleHashEntryData) + + TupleHashEntrySize() + tupleChunkSize + pergroupChunkSize + transitionChunkSize; @@ -1988,7 +1988,7 @@ hash_agg_update_metrics(AggState *aggstate, bool from_tape, int npartitions) if (aggstate->hash_ngroups_current > 0) { aggstate->hashentrysize = - sizeof(TupleHashEntryData) + + TupleHashEntrySize() + (hashkey_mem / (double) aggstate->hash_ngroups_current); } } @@ -2147,11 +2147,7 @@ initialize_hash_entry(AggState *aggstate, TupleHashTable hashtable, if (aggstate->numtrans == 0) return; - pergroup = (AggStatePerGroup) - MemoryContextAlloc(hashtable->tablecxt, - sizeof(AggStatePerGroupData) * aggstate->numtrans); - - entry->additional = pergroup; + pergroup = (AggStatePerGroup) TupleHashEntryGetAdditional(hashtable, entry); /* * Initialize aggregates for new tuple group, lookup_hash_entries() @@ -2213,7 +2209,7 @@ lookup_hash_entries(AggState *aggstate) { if (isnew) initialize_hash_entry(aggstate, hashtable, entry); - pergroup[setno] = entry->additional; + pergroup[setno] = TupleHashEntryGetAdditional(hashtable, entry); } else { @@ -2748,6 +2744,7 @@ agg_refill_hash_table(AggState *aggstate) { TupleTableSlot *spillslot = aggstate->hash_spill_rslot; TupleTableSlot *hashslot = perhash->hashslot; + TupleHashTable hashtable = perhash->hashtable; TupleHashEntry entry; MinimalTuple tuple; uint32 hash; @@ -2766,14 +2763,14 @@ agg_refill_hash_table(AggState *aggstate) prepare_hash_slot(perhash, aggstate->tmpcontext->ecxt_outertuple, hashslot); - entry = LookupTupleHashEntryHash(perhash->hashtable, hashslot, + entry = LookupTupleHashEntryHash(hashtable, hashslot, p_isnew, hash); if (entry != NULL) { if (isnew) - initialize_hash_entry(aggstate, perhash->hashtable, entry); - aggstate->hash_pergroup[batch->setno] = entry->additional; + initialize_hash_entry(aggstate, hashtable, entry); + aggstate->hash_pergroup[batch->setno] = TupleHashEntryGetAdditional(hashtable, entry); advance_aggregates(aggstate); } else @@ -2865,7 +2862,7 @@ agg_retrieve_hash_table_in_memory(AggState *aggstate) ExprContext *econtext; AggStatePerAgg peragg; AggStatePerGroup pergroup; - TupleHashEntryData *entry; + TupleHashEntry entry; TupleTableSlot *firstSlot; TupleTableSlot *result; AggStatePerHash perhash; @@ -2892,6 +2889,7 @@ agg_retrieve_hash_table_in_memory(AggState *aggstate) for (;;) { TupleTableSlot *hashslot = perhash->hashslot; + TupleHashTable hashtable = perhash->hashtable; int i; CHECK_FOR_INTERRUPTS(); @@ -2899,7 +2897,7 @@ agg_retrieve_hash_table_in_memory(AggState *aggstate) /* * Find the next entry in the hash table */ - entry = ScanTupleHashTable(perhash->hashtable, &perhash->hashiter); + entry = ScanTupleHashTable(hashtable, &perhash->hashiter); if (entry == NULL) { int nextset = aggstate->current_set + 1; @@ -2914,7 +2912,7 @@ agg_retrieve_hash_table_in_memory(AggState *aggstate) perhash = &aggstate->perhash[aggstate->current_set]; - ResetTupleHashIterator(perhash->hashtable, &perhash->hashiter); + ResetTupleHashIterator(hashtable, &perhash->hashiter); continue; } @@ -2937,7 +2935,7 @@ agg_retrieve_hash_table_in_memory(AggState *aggstate) * Transform representative tuple back into one with the right * columns. */ - ExecStoreMinimalTuple(entry->firstTuple, hashslot, false); + ExecStoreMinimalTuple(TupleHashEntryGetTuple(entry), hashslot, false); slot_getallattrs(hashslot); ExecClearTuple(firstSlot); @@ -2953,7 +2951,7 @@ agg_retrieve_hash_table_in_memory(AggState *aggstate) } ExecStoreVirtualTuple(firstSlot); - pergroup = (AggStatePerGroup) entry->additional; + pergroup = (AggStatePerGroup) TupleHashEntryGetAdditional(hashtable, entry); /* * Use the representative input tuple for any references to diff --git a/src/backend/executor/nodeSetOp.c b/src/backend/executor/nodeSetOp.c index 5b7ff9c3748..4068481a523 100644 --- a/src/backend/executor/nodeSetOp.c +++ b/src/backend/executor/nodeSetOp.c @@ -424,7 +424,9 @@ setop_fill_hash_table(SetOpState *setopstate) for (;;) { TupleTableSlot *outerslot; + TupleHashTable hashtable = setopstate->hashtable; TupleHashEntryData *entry; + SetOpStatePerGroup pergroup; bool isnew; outerslot = ExecProcNode(outerPlan); @@ -433,20 +435,20 @@ setop_fill_hash_table(SetOpState *setopstate) have_tuples = true; /* Find or build hashtable entry for this tuple's group */ - entry = LookupTupleHashEntry(setopstate->hashtable, + entry = LookupTupleHashEntry(hashtable, outerslot, &isnew, NULL); + pergroup = TupleHashEntryGetAdditional(hashtable, entry); /* If new tuple group, initialize counts to zero */ if (isnew) { - entry->additional = (SetOpStatePerGroup) - MemoryContextAllocZero(setopstate->hashtable->tablecxt, - sizeof(SetOpStatePerGroupData)); + pergroup->numLeft = 0; + pergroup->numRight = 0; } /* Advance the counts */ - ((SetOpStatePerGroup) entry->additional)->numLeft++; + pergroup->numLeft++; /* Must reset expression context after each hashtable lookup */ ResetExprContext(econtext); @@ -465,6 +467,7 @@ setop_fill_hash_table(SetOpState *setopstate) for (;;) { TupleTableSlot *innerslot; + TupleHashTable hashtable = setopstate->hashtable; TupleHashEntryData *entry; innerslot = ExecProcNode(innerPlan); @@ -472,13 +475,17 @@ setop_fill_hash_table(SetOpState *setopstate) break; /* For tuples not seen previously, do not make hashtable entry */ - entry = LookupTupleHashEntry(setopstate->hashtable, + entry = LookupTupleHashEntry(hashtable, innerslot, NULL, NULL); /* Advance the counts if entry is already present */ if (entry) - ((SetOpStatePerGroup) entry->additional)->numRight++; + { + SetOpStatePerGroup pergroup = TupleHashEntryGetAdditional(hashtable, entry); + + pergroup->numRight++; + } /* Must reset expression context after each hashtable lookup */ ResetExprContext(econtext); @@ -496,7 +503,7 @@ setop_fill_hash_table(SetOpState *setopstate) static TupleTableSlot * setop_retrieve_hash_table(SetOpState *setopstate) { - TupleHashEntryData *entry; + TupleHashEntry entry; TupleTableSlot *resultTupleSlot; /* @@ -509,12 +516,15 @@ setop_retrieve_hash_table(SetOpState *setopstate) */ while (!setopstate->setop_done) { + TupleHashTable hashtable = setopstate->hashtable; + SetOpStatePerGroup pergroup; + CHECK_FOR_INTERRUPTS(); /* * Find the next entry in the hash table */ - entry = ScanTupleHashTable(setopstate->hashtable, &setopstate->hashiter); + entry = ScanTupleHashTable(hashtable, &setopstate->hashiter); if (entry == NULL) { /* No more entries in hashtable, so done */ @@ -526,12 +536,13 @@ setop_retrieve_hash_table(SetOpState *setopstate) * See if we should emit any copies of this tuple, and if so return * the first copy. */ - set_output_count(setopstate, (SetOpStatePerGroup) entry->additional); + pergroup = TupleHashEntryGetAdditional(hashtable, entry); + set_output_count(setopstate, pergroup); if (setopstate->numOutput > 0) { setopstate->numOutput--; - return ExecStoreMinimalTuple(entry->firstTuple, + return ExecStoreMinimalTuple(TupleHashEntryGetTuple(entry), resultTupleSlot, false); } diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index 49767ed6a52..f7f6fc2da0b 100644 --- a/src/backend/executor/nodeSubplan.c +++ b/src/backend/executor/nodeSubplan.c @@ -753,7 +753,7 @@ findPartialMatch(TupleHashTable hashtable, TupleTableSlot *slot, { CHECK_FOR_INTERRUPTS(); - ExecStoreMinimalTuple(entry->firstTuple, hashtable->tableslot, false); + ExecStoreMinimalTuple(TupleHashEntryGetTuple(entry), hashtable->tableslot, false); if (!execTuplesUnequal(slot, hashtable->tableslot, numCols, keyColIdx, eqfunctions, diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index 0db5d18ba22..69396a9d7f8 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -158,6 +158,40 @@ extern TupleHashEntry FindTupleHashEntry(TupleHashTable hashtable, ExprState *hashexpr); extern void ResetTupleHashTable(TupleHashTable hashtable); +#ifndef FRONTEND +/* + * Return size of the hash bucket. Useful for estimating memory usage. + */ +static inline size_t +TupleHashEntrySize(void) +{ + return sizeof(TupleHashEntryData); +} + +/* + * Return tuple from hash entry. + */ +static inline MinimalTuple +TupleHashEntryGetTuple(TupleHashEntry entry) +{ + return entry->firstTuple; +} + +/* + * Get a pointer into the additional space allocated for this entry. The + * memory will be maxaligned and zeroed. + * + * The amount of space available is the additionalsize requested in the call + * to BuildTupleHashTable(). If additionalsize was specified as zero, return + * NULL. + */ +static inline void * +TupleHashEntryGetAdditional(TupleHashTable hashtable, TupleHashEntry entry) +{ + return entry->additional; +} +#endif + /* * prototypes from functions in execJunk.c */ diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index b5539ddb41e..7df25d7e64f 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -863,6 +863,7 @@ typedef struct TupleHashTableData Oid *tab_collations; /* collations for hash and comparison */ MemoryContext tablecxt; /* memory context containing table */ MemoryContext tempcxt; /* context for function evaluations */ + Size additionalsize; /* size of additional data */ TupleTableSlot *tableslot; /* slot for referencing table entries */ /* The following fields are set transiently for each table search: */ TupleTableSlot *inputslot; /* current input tuple's slot */ |