/* these are in nodes/execnodes.h: */ /* typedef struct HashJoinTupleData *HashJoinTuple; */ /* typedef struct HashJoinTableData *HashJoinTable; */
typedefstruct HashJoinTupleData
{ /* link to next tuple in same bucket */ union
{ struct HashJoinTupleData *unshared;
dsa_pointer shared;
} next;
uint32 hashvalue; /* tuple's hash code */ /* Tuple data, in MinimalTuple format, follows on a MAXALIGN boundary */
} HashJoinTupleData;
/* *Toreducepallocoverhead,theHashJoinTuplesforthecurrentbatchare *packedin32kBbuffersinsteadofpallocingeachtupleindividually.
*/ typedefstruct HashMemoryChunkData
{ int ntuples; /* number of tuples stored in this chunk */
size_t maxlen; /* size of the chunk's tuple buffer */
size_t used; /* number of buffer bytes already used */
/* pointer to the next chunk (linked list) */ union
{ struct HashMemoryChunkData *unshared;
dsa_pointer shared;
} next;
/* Accessor for inner batch tuplestore following a ParallelHashJoinBatch. */ #define ParallelHashJoinBatchInner(batch) \
((SharedTuplestore *) \
((char *) (batch) + MAXALIGN(sizeof(ParallelHashJoinBatch))))
/* Accessor for outer batch tuplestore following a ParallelHashJoinBatch. */ #define ParallelHashJoinBatchOuter(batch, nparticipants) \
((SharedTuplestore *) \
((char *) ParallelHashJoinBatchInner(batch) + \
MAXALIGN(sts_estimate(nparticipants))))
/* Total size of a ParallelHashJoinBatch and tuplestores. */ #define EstimateParallelHashJoinBatch(hashtable) \
(MAXALIGN(sizeof(ParallelHashJoinBatch)) + \
MAXALIGN(sts_estimate((hashtable)->parallel_state->nparticipants)) * 2)
/* Accessor for the nth ParallelHashJoinBatch given the base. */ #define NthParallelHashJoinBatch(base, n) \
((ParallelHashJoinBatch *) \
((char *) (base) + \
EstimateParallelHashJoinBatch(hashtable) * (n)))
/* *Eachbackendrequiresasmallamountofper-batchstatetointeractwith *eachParallelHashJoinBatch.
*/ typedefstruct ParallelHashJoinBatchAccessor
{
ParallelHashJoinBatch *shared; /* pointer to shared state */
/* Per-backend partial counters to reduce contention. */
size_t preallocated; /* pre-allocated space for this backend */
size_t ntuples; /* number of tuples */
size_t size; /* size of partition in memory */
size_t estimated_size; /* size of partition on disk */
size_t old_ntuples; /* how many tuples before repartitioning? */ bool at_least_one_chunk; /* has this backend allocated a chunk? */ bool outer_eof; /* has this process hit end of batch? */ bool done; /* flag to remember that a batch is done */
SharedTuplestoreAccessor *inner_tuples;
SharedTuplestoreAccessor *outer_tuples;
} ParallelHashJoinBatchAccessor;
/* *Whilehashingtheinnerrelation,anyparticipantmightdeterminethatit's *timetoincreasethenumberofbucketstoreducetheloadfactororbatches *toreducethememorysize.Thisisindicatedbysettingthegrowthflagto *thesevalues.
*/ typedefenum ParallelHashGrowth
{ /* The current dimensions are sufficient. */
PHJ_GROWTH_OK, /* The load factor is too high, so we need to add buckets. */
PHJ_GROWTH_NEED_MORE_BUCKETS, /* The memory budget would be exhausted, so we need to repartition. */
PHJ_GROWTH_NEED_MORE_BATCHES, /* Repartitioning didn't help last time, so don't try to do that again. */
PHJ_GROWTH_DISABLED,
} ParallelHashGrowth;
/* *ThesharedstateusedtocoordinateaParallelHashJoin.Thisisstored *intheDSMsegment.
*/ typedefstruct ParallelHashJoinState
{
dsa_pointer batches; /* array of ParallelHashJoinBatch */
dsa_pointer old_batches; /* previous generation during repartition */ int nbatch; /* number of batches now */ int old_nbatch; /* previous number of batches */ int nbuckets; /* number of buckets */
ParallelHashGrowth growth; /* control batch/bucket growth */
dsa_pointer chunk_work_queue; /* chunk work queue */ int nparticipants;
size_t space_allowed;
size_t total_tuples; /* total number of inner tuples */
LWLock lock; /* lock protecting the above */
Barrier build_barrier; /* synchronization for the build phases */
Barrier grow_batches_barrier;
Barrier grow_buckets_barrier;
pg_atomic_uint32 distributor; /* counter for load balancing */
SharedFileSet fileset; /* space for shared temporary files */
} ParallelHashJoinState;
/* The phases for building batches, used by build_barrier. */ #define PHJ_BUILD_ELECT 0 #define PHJ_BUILD_ALLOCATE 1 #define PHJ_BUILD_HASH_INNER 2 #define PHJ_BUILD_HASH_OUTER 3 #define PHJ_BUILD_RUN 4 #define PHJ_BUILD_FREE 5
/* The phases for probing each batch, used by for batch_barrier. */ #define PHJ_BATCH_ELECT 0 #define PHJ_BATCH_ALLOCATE 1 #define PHJ_BATCH_LOAD 2 #define PHJ_BATCH_PROBE 3 #define PHJ_BATCH_SCAN 4 #define PHJ_BATCH_FREE 5
/* The phases of batch growth while hashing, for grow_batches_barrier. */ #define PHJ_GROW_BATCHES_ELECT 0 #define PHJ_GROW_BATCHES_REALLOCATE 1 #define PHJ_GROW_BATCHES_REPARTITION 2 #define PHJ_GROW_BATCHES_DECIDE 3 #define PHJ_GROW_BATCHES_FINISH 4 #define PHJ_GROW_BATCHES_PHASE(n) ((n) % 5) /* circular phases */
/* The phases of bucket growth while hashing, for grow_buckets_barrier. */ #define PHJ_GROW_BUCKETS_ELECT 0 #define PHJ_GROW_BUCKETS_REALLOCATE 1 #define PHJ_GROW_BUCKETS_REINSERT 2 #define PHJ_GROW_BUCKETS_PHASE(n) ((n) % 3) /* circular phases */
typedefstruct HashJoinTableData
{ int nbuckets; /* # buckets in the in-memory hash table */ int log2_nbuckets; /* its log2 (nbuckets must be a power of 2) */
int nbuckets_original; /* # buckets when starting the first hash */ int nbuckets_optimal; /* optimal # buckets (per batch) */ int log2_nbuckets_optimal; /* log2(nbuckets_optimal) */
/* buckets[i] is head of list of tuples in i'th in-memory bucket */ union
{ /* unshared array is per-batch storage, as are all the tuples */ struct HashJoinTupleData **unshared; /* shared array is per-query DSA area, as are all the tuples */
dsa_pointer_atomic *shared;
} buckets;
bool skewEnabled; /* are we using skew optimization? */
HashSkewBucket **skewBucket; /* hashtable of skew buckets */ int skewBucketLen; /* size of skewBucket array (a power of 2!) */ int nSkewBuckets; /* number of active skew buckets */ int *skewBucketNums; /* array indexes of active skew buckets */
int nbatch; /* number of batches */ int curbatch; /* current batch #; 0 during 1st pass */
int nbatch_original; /* nbatch when we started inner scan */ int nbatch_outstart; /* nbatch when we started outer scan */
bool growEnabled; /* flag to shut off nbatch increases */
double totalTuples; /* # tuples obtained from inner plan */ double partialTuples; /* # tuples obtained from inner plan by me */ double skewTuples; /* # tuples inserted into skew tuples */
Size spaceUsed; /* memory space currently used by tuples */
Size spaceAllowed; /* upper limit for space used */
Size spacePeak; /* peak space used */
Size spaceUsedSkew; /* skew hash table's current space usage */
Size spaceAllowedSkew; /* upper limit for skew hashtable */
MemoryContext hashCxt; /* context for whole-hash-join storage */
MemoryContext batchCxt; /* context for this-batch-only storage */
MemoryContext spillCxt; /* context for spilling to temp files */
/* used for dense allocation of tuples (into linked chunks) */
HashMemoryChunk chunks; /* one list for the whole batch */
/* Shared and private state for Parallel Hash. */
HashMemoryChunk current_chunk; /* this backend's current chunk */
dsa_area *area; /* DSA area to allocate memory from */
ParallelHashJoinState *parallel_state;
ParallelHashJoinBatchAccessor *batches;
dsa_pointer current_chunk_shared;
} HashJoinTableData;
#endif/* HASHJOIN_H */
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.20 Sekunden
(vorverarbeitet am 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.