diff options
author | Jeff Davis <jdavis@postgresql.org> | 2025-01-10 17:14:37 -0800 |
---|---|---|
committer | Jeff Davis <jdavis@postgresql.org> | 2025-01-10 17:14:37 -0800 |
commit | e0ece2a981ee9068f50c4423e303836c2585eb02 (patch) | |
tree | b5a61a16ff16405c3c3bcbb4f44089648e166d12 /src/backend/executor/execGrouping.c | |
parent | 34c6e652425fde42c2746f749e31d196fc0d5538 (diff) | |
download | postgresql-e0ece2a981ee9068f50c4423e303836c2585eb02.tar.gz postgresql-e0ece2a981ee9068f50c4423e303836c2585eb02.zip |
TupleHashTable: store additional data along with tuple.
Previously, the caller needed to allocate the memory and the
TupleHashTable would store a pointer to it. That wastes space for the
palloc overhead as well as the size of the pointer itself.
Now, the TupleHashTable relies on the caller to correctly specify the
additionalsize, and allocates that amount of space. The caller can
then request a pointer into that space.
Discussion: https://postgr.es/m/b9cbf0219a9859dc8d240311643ff4362fd9602c.camel@j-davis.com
Reviewed-by: Heikki Linnakangas
Diffstat (limited to 'src/backend/executor/execGrouping.c')
-rw-r--r-- | src/backend/executor/execGrouping.c | 57 |
1 files changed, 55 insertions, 2 deletions
diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c index 33b124fbb0a..40f1776a7be 100644 --- a/src/backend/executor/execGrouping.c +++ b/src/backend/executor/execGrouping.c @@ -20,6 +20,13 @@ #include "miscadmin.h" #include "utils/lsyscache.h" +typedef struct TupleHashEntryData +{ + MinimalTuple firstTuple; /* copy of first tuple in this group */ + uint32 status; /* hash status */ + uint32 hash; /* hash value (cached) */ +} TupleHashEntryData; + static int TupleHashTableMatch(struct tuplehash_hash *tb, const MinimalTuple tuple1, const MinimalTuple tuple2); static inline uint32 TupleHashTableHash_internal(struct tuplehash_hash *tb, const MinimalTuple tuple); @@ -196,6 +203,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; @@ -274,6 +282,15 @@ ResetTupleHashTable(TupleHashTable hashtable) } /* + * Return size of the hash bucket. Useful for estimating memory usage. + */ +size_t +TupleHashEntrySize(void) +{ + return sizeof(TupleHashEntryData); +} + +/* * Find or create a hashtable entry for the tuple group containing the * given tuple. The tuple must be the same type as the hashtable entries. * @@ -339,6 +356,24 @@ TupleHashTableHash(TupleHashTable hashtable, TupleTableSlot *slot) return hash; } +MinimalTuple +TupleHashEntryGetTuple(TupleHashEntry entry) +{ + return entry->firstTuple; +} + +/* + * Get a pointer into the additional space allocated for this entry. The + * amount of space available is the additionalsize specified to + * BuildTupleHashTable(). If additionalsize was specified as zero, no + * additional space is available and this function should not be called. + */ +void * +TupleHashEntryGetAdditional(TupleHashEntry entry) +{ + return (char *) entry->firstTuple + MAXALIGN(entry->firstTuple->t_len); +} + /* * A variant of LookupTupleHashEntry for callers that have already computed * the hash value. @@ -477,13 +512,31 @@ LookupTupleHashEntry_internal(TupleHashTable hashtable, TupleTableSlot *slot, } else { + MinimalTuple firstTuple; + size_t totalsize; /* including alignment and additionalsize */ + /* 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); + firstTuple = ExecCopySlotMinimalTuple(slot); + + /* + * Allocate additional space right after the MinimalTuple of size + * additionalsize. The caller can get a pointer to this data with + * TupleHashEntryGetAdditional(), and store arbitrary data there. + * + * This avoids the need to store an extra pointer or allocate an + * additional chunk, which would waste memory. + */ + totalsize = MAXALIGN(firstTuple->t_len) + hashtable->additionalsize; + firstTuple = repalloc(firstTuple, totalsize); + memset((char *) firstTuple + firstTuple->t_len, 0, + totalsize - firstTuple->t_len); + + entry->firstTuple = firstTuple; } } else |