mirror of
https://github.com/postgres/postgres.git
synced 2025-07-31 22:04:40 +03:00
Create accessor functions for TupleHashEntry.
Refactor for upcoming optimizations. Reviewed-by: David Rowley <dgrowleyml@gmail.com> Discussion: https://postgr.es/m/1cc3b400a0e8eead18ff967436fa9e42c0c14cfb.camel@j-davis.com
This commit is contained in:
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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 */
|
||||
|
Reference in New Issue
Block a user