PostgreSQL Source Code  git master
nodeHash.h File Reference
#include "access/parallel.h"
#include "nodes/execnodes.h"
Include dependency graph for nodeHash.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

HashStateExecInitHash (Hash *node, EState *estate, int eflags)
 
NodeMultiExecHash (HashState *node)
 
void ExecEndHash (HashState *node)
 
void ExecReScanHash (HashState *node)
 
HashJoinTable ExecHashTableCreate (HashState *state, List *hashOperators, List *hashCollations, bool keepNulls)
 
void ExecParallelHashTableAlloc (HashJoinTable hashtable, int batchno)
 
void ExecHashTableDestroy (HashJoinTable hashtable)
 
void ExecHashTableDetach (HashJoinTable hashtable)
 
void ExecHashTableDetachBatch (HashJoinTable hashtable)
 
void ExecParallelHashTableSetCurrentBatch (HashJoinTable hashtable, int batchno)
 
void ExecHashTableInsert (HashJoinTable hashtable, TupleTableSlot *slot, uint32 hashvalue)
 
void ExecParallelHashTableInsert (HashJoinTable hashtable, TupleTableSlot *slot, uint32 hashvalue)
 
void ExecParallelHashTableInsertCurrentBatch (HashJoinTable hashtable, TupleTableSlot *slot, uint32 hashvalue)
 
bool ExecHashGetHashValue (HashJoinTable hashtable, ExprContext *econtext, List *hashkeys, bool outer_tuple, bool keep_nulls, uint32 *hashvalue)
 
void ExecHashGetBucketAndBatch (HashJoinTable hashtable, uint32 hashvalue, int *bucketno, int *batchno)
 
bool ExecScanHashBucket (HashJoinState *hjstate, ExprContext *econtext)
 
bool ExecParallelScanHashBucket (HashJoinState *hjstate, ExprContext *econtext)
 
void ExecPrepHashTableForUnmatched (HashJoinState *hjstate)
 
bool ExecScanHashTableForUnmatched (HashJoinState *hjstate, ExprContext *econtext)
 
void ExecHashTableReset (HashJoinTable hashtable)
 
void ExecHashTableResetMatchFlags (HashJoinTable hashtable)
 
void ExecChooseHashTableSize (double ntuples, int tupwidth, bool useskew, bool try_combined_work_mem, int parallel_workers, size_t *space_allowed, int *numbuckets, int *numbatches, int *num_skew_mcvs)
 
int ExecHashGetSkewBucket (HashJoinTable hashtable, uint32 hashvalue)
 
void ExecHashEstimate (HashState *node, ParallelContext *pcxt)
 
void ExecHashInitializeDSM (HashState *node, ParallelContext *pcxt)
 
void ExecHashInitializeWorker (HashState *node, ParallelWorkerContext *pwcxt)
 
void ExecHashRetrieveInstrumentation (HashState *node)
 
void ExecShutdownHash (HashState *node)
 
void ExecHashGetInstrumentation (HashInstrumentation *instrument, HashJoinTable hashtable)
 

Function Documentation

◆ ExecChooseHashTableSize()

void ExecChooseHashTableSize ( double  ntuples,
int  tupwidth,
bool  useskew,
bool  try_combined_work_mem,
int  parallel_workers,
size_t *  space_allowed,
int *  numbuckets,
int *  numbatches,
int *  num_skew_mcvs 
)

Definition at line 666 of file nodeHash.c.

References Assert, ExecChooseHashTableSize(), HJTUPLE_OVERHEAD, Max, MAXALIGN, MaxAllocSize, Min, my_log2(), NTUP_PER_BUCKET, SizeofMinimalTupleHeader, SKEW_BUCKET_OVERHEAD, SKEW_WORK_MEM_PERCENT, and work_mem.

Referenced by ExecChooseHashTableSize(), ExecHashTableCreate(), and initial_cost_hashjoin().

673 {
674  int tupsize;
675  double inner_rel_bytes;
676  long bucket_bytes;
677  long hash_table_bytes;
678  long skew_table_bytes;
679  long max_pointers;
680  long mppow2;
681  int nbatch = 1;
682  int nbuckets;
683  double dbuckets;
684 
685  /* Force a plausible relation size if no info */
686  if (ntuples <= 0.0)
687  ntuples = 1000.0;
688 
689  /*
690  * Estimate tupsize based on footprint of tuple in hashtable... note this
691  * does not allow for any palloc overhead. The manipulations of spaceUsed
692  * don't count palloc overhead either.
693  */
694  tupsize = HJTUPLE_OVERHEAD +
696  MAXALIGN(tupwidth);
697  inner_rel_bytes = ntuples * tupsize;
698 
699  /*
700  * Target in-memory hashtable size is work_mem kilobytes.
701  */
702  hash_table_bytes = work_mem * 1024L;
703 
704  /*
705  * Parallel Hash tries to use the combined work_mem of all workers to
706  * avoid the need to batch. If that won't work, it falls back to work_mem
707  * per worker and tries to process batches in parallel.
708  */
709  if (try_combined_work_mem)
710  hash_table_bytes += hash_table_bytes * parallel_workers;
711 
712  *space_allowed = hash_table_bytes;
713 
714  /*
715  * If skew optimization is possible, estimate the number of skew buckets
716  * that will fit in the memory allowed, and decrement the assumed space
717  * available for the main hash table accordingly.
718  *
719  * We make the optimistic assumption that each skew bucket will contain
720  * one inner-relation tuple. If that turns out to be low, we will recover
721  * at runtime by reducing the number of skew buckets.
722  *
723  * hashtable->skewBucket will have up to 8 times as many HashSkewBucket
724  * pointers as the number of MCVs we allow, since ExecHashBuildSkewHash
725  * will round up to the next power of 2 and then multiply by 4 to reduce
726  * collisions.
727  */
728  if (useskew)
729  {
730  skew_table_bytes = hash_table_bytes * SKEW_WORK_MEM_PERCENT / 100;
731 
732  /*----------
733  * Divisor is:
734  * size of a hash tuple +
735  * worst-case size of skewBucket[] per MCV +
736  * size of skewBucketNums[] entry +
737  * size of skew bucket struct itself
738  *----------
739  */
740  *num_skew_mcvs = skew_table_bytes / (tupsize +
741  (8 * sizeof(HashSkewBucket *)) +
742  sizeof(int) +
744  if (*num_skew_mcvs > 0)
745  hash_table_bytes -= skew_table_bytes;
746  }
747  else
748  *num_skew_mcvs = 0;
749 
750  /*
751  * Set nbuckets to achieve an average bucket load of NTUP_PER_BUCKET when
752  * memory is filled, assuming a single batch; but limit the value so that
753  * the pointer arrays we'll try to allocate do not exceed work_mem nor
754  * MaxAllocSize.
755  *
756  * Note that both nbuckets and nbatch must be powers of 2 to make
757  * ExecHashGetBucketAndBatch fast.
758  */
759  max_pointers = *space_allowed / sizeof(HashJoinTuple);
760  max_pointers = Min(max_pointers, MaxAllocSize / sizeof(HashJoinTuple));
761  /* If max_pointers isn't a power of 2, must round it down to one */
762  mppow2 = 1L << my_log2(max_pointers);
763  if (max_pointers != mppow2)
764  max_pointers = mppow2 / 2;
765 
766  /* Also ensure we avoid integer overflow in nbatch and nbuckets */
767  /* (this step is redundant given the current value of MaxAllocSize) */
768  max_pointers = Min(max_pointers, INT_MAX / 2);
769 
770  dbuckets = ceil(ntuples / NTUP_PER_BUCKET);
771  dbuckets = Min(dbuckets, max_pointers);
772  nbuckets = (int) dbuckets;
773  /* don't let nbuckets be really small, though ... */
774  nbuckets = Max(nbuckets, 1024);
775  /* ... and force it to be a power of 2. */
776  nbuckets = 1 << my_log2(nbuckets);
777 
778  /*
779  * If there's not enough space to store the projected number of tuples and
780  * the required bucket headers, we will need multiple batches.
781  */
782  bucket_bytes = sizeof(HashJoinTuple) * nbuckets;
783  if (inner_rel_bytes + bucket_bytes > hash_table_bytes)
784  {
785  /* We'll need multiple batches */
786  long lbuckets;
787  double dbatch;
788  int minbatch;
789  long bucket_size;
790 
791  /*
792  * If Parallel Hash with combined work_mem would still need multiple
793  * batches, we'll have to fall back to regular work_mem budget.
794  */
795  if (try_combined_work_mem)
796  {
797  ExecChooseHashTableSize(ntuples, tupwidth, useskew,
798  false, parallel_workers,
799  space_allowed,
800  numbuckets,
801  numbatches,
802  num_skew_mcvs);
803  return;
804  }
805 
806  /*
807  * Estimate the number of buckets we'll want to have when work_mem is
808  * entirely full. Each bucket will contain a bucket pointer plus
809  * NTUP_PER_BUCKET tuples, whose projected size already includes
810  * overhead for the hash code, pointer to the next tuple, etc.
811  */
812  bucket_size = (tupsize * NTUP_PER_BUCKET + sizeof(HashJoinTuple));
813  lbuckets = 1L << my_log2(hash_table_bytes / bucket_size);
814  lbuckets = Min(lbuckets, max_pointers);
815  nbuckets = (int) lbuckets;
816  nbuckets = 1 << my_log2(nbuckets);
817  bucket_bytes = nbuckets * sizeof(HashJoinTuple);
818 
819  /*
820  * Buckets are simple pointers to hashjoin tuples, while tupsize
821  * includes the pointer, hash code, and MinimalTupleData. So buckets
822  * should never really exceed 25% of work_mem (even for
823  * NTUP_PER_BUCKET=1); except maybe for work_mem values that are not
824  * 2^N bytes, where we might get more because of doubling. So let's
825  * look for 50% here.
826  */
827  Assert(bucket_bytes <= hash_table_bytes / 2);
828 
829  /* Calculate required number of batches. */
830  dbatch = ceil(inner_rel_bytes / (hash_table_bytes - bucket_bytes));
831  dbatch = Min(dbatch, max_pointers);
832  minbatch = (int) dbatch;
833  nbatch = 2;
834  while (nbatch < minbatch)
835  nbatch <<= 1;
836  }
837 
838  Assert(nbuckets > 0);
839  Assert(nbatch > 0);
840 
841  *numbuckets = nbuckets;
842  *numbatches = nbatch;
843 }
#define SKEW_BUCKET_OVERHEAD
Definition: hashjoin.h:108
#define Min(x, y)
Definition: c.h:911
struct HashJoinTupleData * HashJoinTuple
Definition: execnodes.h:1923
int my_log2(long num)
Definition: dynahash.c:1718
#define MaxAllocSize
Definition: memutils.h:40
#define SizeofMinimalTupleHeader
Definition: htup_details.h:649
#define NTUP_PER_BUCKET
Definition: nodeHash.c:663
int work_mem
Definition: globals.c:121
#define HJTUPLE_OVERHEAD
Definition: hashjoin.h:79
#define Max(x, y)
Definition: c.h:905
#define Assert(condition)
Definition: c.h:739
#define MAXALIGN(LEN)
Definition: c.h:692
#define SKEW_WORK_MEM_PERCENT
Definition: hashjoin.h:110
void ExecChooseHashTableSize(double ntuples, int tupwidth, bool useskew, bool try_combined_work_mem, int parallel_workers, size_t *space_allowed, int *numbuckets, int *numbatches, int *num_skew_mcvs)
Definition: nodeHash.c:666

◆ ExecEndHash()

void ExecEndHash ( HashState node)

Definition at line 405 of file nodeHash.c.

References ExecEndNode(), ExecFreeExprContext(), outerPlan, outerPlanState, and HashState::ps.

Referenced by ExecEndNode().

406 {
408 
409  /*
410  * free exprcontext
411  */
412  ExecFreeExprContext(&node->ps);
413 
414  /*
415  * shut down the subplan
416  */
417  outerPlan = outerPlanState(node);
418  ExecEndNode(outerPlan);
419 }
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:537
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:614
#define outerPlanState(node)
Definition: execnodes.h:1033
PlanState ps
Definition: execnodes.h:2266
#define outerPlan(node)
Definition: plannodes.h:172

◆ ExecHashEstimate()

void ExecHashEstimate ( HashState node,
ParallelContext pcxt 
)

Definition at line 2569 of file nodeHash.c.

References add_size(), ParallelContext::estimator, PlanState::instrument, mul_size(), ParallelContext::nworkers, offsetof, HashState::ps, shm_toc_estimate_chunk, and shm_toc_estimate_keys.

Referenced by ExecParallelEstimate().

2570 {
2571  size_t size;
2572 
2573  /* don't need this if not instrumenting or no workers */
2574  if (!node->ps.instrument || pcxt->nworkers == 0)
2575  return;
2576 
2577  size = mul_size(pcxt->nworkers, sizeof(HashInstrumentation));
2578  size = add_size(size, offsetof(SharedHashInfo, hinstrument));
2579  shm_toc_estimate_chunk(&pcxt->estimator, size);
2580  shm_toc_estimate_keys(&pcxt->estimator, 1);
2581 }
Instrumentation * instrument
Definition: execnodes.h:949
shm_toc_estimator estimator
Definition: parallel.h:41
#define shm_toc_estimate_chunk(e, sz)
Definition: shm_toc.h:51
PlanState ps
Definition: execnodes.h:2266
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492
Size add_size(Size s1, Size s2)
Definition: shmem.c:475
#define shm_toc_estimate_keys(e, cnt)
Definition: shm_toc.h:53
#define offsetof(type, field)
Definition: c.h:662

◆ ExecHashGetBucketAndBatch()

void ExecHashGetBucketAndBatch ( HashJoinTable  hashtable,
uint32  hashvalue,
int *  bucketno,
int *  batchno 
)

Definition at line 1895 of file nodeHash.c.

References HashJoinTableData::log2_nbuckets, HashJoinTableData::nbatch, and HashJoinTableData::nbuckets.

Referenced by ExecHashIncreaseNumBatches(), ExecHashIncreaseNumBuckets(), ExecHashJoinImpl(), ExecHashRemoveNextSkewBucket(), ExecHashTableInsert(), ExecParallelHashIncreaseNumBuckets(), ExecParallelHashJoinPartitionOuter(), ExecParallelHashRepartitionFirst(), ExecParallelHashRepartitionRest(), ExecParallelHashTableInsert(), and ExecParallelHashTableInsertCurrentBatch().

1899 {
1900  uint32 nbuckets = (uint32) hashtable->nbuckets;
1901  uint32 nbatch = (uint32) hashtable->nbatch;
1902 
1903  if (nbatch > 1)
1904  {
1905  /* we can do MOD by masking, DIV by shifting */
1906  *bucketno = hashvalue & (nbuckets - 1);
1907  *batchno = (hashvalue >> hashtable->log2_nbuckets) & (nbatch - 1);
1908  }
1909  else
1910  {
1911  *bucketno = hashvalue & (nbuckets - 1);
1912  *batchno = 0;
1913  }
1914 }
unsigned int uint32
Definition: c.h:359

◆ ExecHashGetHashValue()

bool ExecHashGetHashValue ( HashJoinTable  hashtable,
ExprContext econtext,
List hashkeys,
bool  outer_tuple,
bool  keep_nulls,
uint32 hashvalue 
)

Definition at line 1791 of file nodeHash.c.

References HashJoinTableData::collations, DatumGetUInt32, ExprContext::ecxt_per_tuple_memory, ExecEvalExpr(), FunctionCall1Coll(), HashJoinTableData::hashStrict, i, HashJoinTableData::inner_hashfunctions, lfirst, MemoryContextSwitchTo(), HashJoinTableData::outer_hashfunctions, and ResetExprContext.

Referenced by ExecHashJoinOuterGetTuple(), ExecParallelHashJoinOuterGetTuple(), ExecParallelHashJoinPartitionOuter(), MultiExecParallelHash(), and MultiExecPrivateHash().

1797 {
1798  uint32 hashkey = 0;
1799  FmgrInfo *hashfunctions;
1800  ListCell *hk;
1801  int i = 0;
1802  MemoryContext oldContext;
1803 
1804  /*
1805  * We reset the eval context each time to reclaim any memory leaked in the
1806  * hashkey expressions.
1807  */
1808  ResetExprContext(econtext);
1809 
1810  oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
1811 
1812  if (outer_tuple)
1813  hashfunctions = hashtable->outer_hashfunctions;
1814  else
1815  hashfunctions = hashtable->inner_hashfunctions;
1816 
1817  foreach(hk, hashkeys)
1818  {
1819  ExprState *keyexpr = (ExprState *) lfirst(hk);
1820  Datum keyval;
1821  bool isNull;
1822 
1823  /* rotate hashkey left 1 bit at each step */
1824  hashkey = (hashkey << 1) | ((hashkey & 0x80000000) ? 1 : 0);
1825 
1826  /*
1827  * Get the join attribute value of the tuple
1828  */
1829  keyval = ExecEvalExpr(keyexpr, econtext, &isNull);
1830 
1831  /*
1832  * If the attribute is NULL, and the join operator is strict, then
1833  * this tuple cannot pass the join qual so we can reject it
1834  * immediately (unless we're scanning the outside of an outer join, in
1835  * which case we must not reject it). Otherwise we act like the
1836  * hashcode of NULL is zero (this will support operators that act like
1837  * IS NOT DISTINCT, though not any more-random behavior). We treat
1838  * the hash support function as strict even if the operator is not.
1839  *
1840  * Note: currently, all hashjoinable operators must be strict since
1841  * the hash index AM assumes that. However, it takes so little extra
1842  * code here to allow non-strict that we may as well do it.
1843  */
1844  if (isNull)
1845  {
1846  if (hashtable->hashStrict[i] && !keep_nulls)
1847  {
1848  MemoryContextSwitchTo(oldContext);
1849  return false; /* cannot match */
1850  }
1851  /* else, leave hashkey unmodified, equivalent to hashcode 0 */
1852  }
1853  else
1854  {
1855  /* Compute the hash function */
1856  uint32 hkey;
1857 
1858  hkey = DatumGetUInt32(FunctionCall1Coll(&hashfunctions[i], hashtable->collations[i], keyval));
1859  hashkey ^= hkey;
1860  }
1861 
1862  i++;
1863  }
1864 
1865  MemoryContextSwitchTo(oldContext);
1866 
1867  *hashvalue = hashkey;
1868  return true;
1869 }
#define DatumGetUInt32(X)
Definition: postgres.h:486
Definition: fmgr.h:56
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:231
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
FmgrInfo * inner_hashfunctions
Definition: hashjoin.h:338
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:285
unsigned int uint32
Definition: c.h:359
FmgrInfo * outer_hashfunctions
Definition: hashjoin.h:337
uintptr_t Datum
Definition: postgres.h:367
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1130
#define lfirst(lc)
Definition: pg_list.h:190
int i
bool * hashStrict
Definition: hashjoin.h:339
#define ResetExprContext(econtext)
Definition: executor.h:495

◆ ExecHashGetInstrumentation()

void ExecHashGetInstrumentation ( HashInstrumentation instrument,
HashJoinTable  hashtable 
)

◆ ExecHashGetSkewBucket()

int ExecHashGetSkewBucket ( HashJoinTable  hashtable,
uint32  hashvalue 
)

Definition at line 2364 of file nodeHash.c.

References HashSkewBucket::hashvalue, INVALID_SKEW_BUCKET_NO, HashJoinTableData::skewBucket, HashJoinTableData::skewBucketLen, and HashJoinTableData::skewEnabled.

Referenced by ExecHashJoinImpl(), and MultiExecPrivateHash().

2365 {
2366  int bucket;
2367 
2368  /*
2369  * Always return INVALID_SKEW_BUCKET_NO if not doing skew optimization (in
2370  * particular, this happens after the initial batch is done).
2371  */
2372  if (!hashtable->skewEnabled)
2373  return INVALID_SKEW_BUCKET_NO;
2374 
2375  /*
2376  * Since skewBucketLen is a power of 2, we can do a modulo by ANDing.
2377  */
2378  bucket = hashvalue & (hashtable->skewBucketLen - 1);
2379 
2380  /*
2381  * While we have not hit a hole in the hashtable and have not hit the
2382  * desired bucket, we have collided with some other hash value, so try the
2383  * next bucket location.
2384  */
2385  while (hashtable->skewBucket[bucket] != NULL &&
2386  hashtable->skewBucket[bucket]->hashvalue != hashvalue)
2387  bucket = (bucket + 1) & (hashtable->skewBucketLen - 1);
2388 
2389  /*
2390  * Found the desired bucket?
2391  */
2392  if (hashtable->skewBucket[bucket] != NULL)
2393  return bucket;
2394 
2395  /*
2396  * There must not be any hashtable entry for this hash value.
2397  */
2398  return INVALID_SKEW_BUCKET_NO;
2399 }
#define INVALID_SKEW_BUCKET_NO
Definition: hashjoin.h:109
HashSkewBucket ** skewBucket
Definition: hashjoin.h:305
uint32 hashvalue
Definition: hashjoin.h:104

◆ ExecHashInitializeDSM()

void ExecHashInitializeDSM ( HashState node,
ParallelContext pcxt 
)

Definition at line 2588 of file nodeHash.c.

References PlanState::instrument, SharedHashInfo::num_workers, ParallelContext::nworkers, offsetof, PlanState::plan, Plan::plan_node_id, HashState::ps, HashState::shared_info, shm_toc_allocate(), shm_toc_insert(), and ParallelContext::toc.

Referenced by ExecParallelInitializeDSM().

2589 {
2590  size_t size;
2591 
2592  /* don't need this if not instrumenting or no workers */
2593  if (!node->ps.instrument || pcxt->nworkers == 0)
2594  return;
2595 
2596  size = offsetof(SharedHashInfo, hinstrument) +
2597  pcxt->nworkers * sizeof(HashInstrumentation);
2598  node->shared_info = (SharedHashInfo *) shm_toc_allocate(pcxt->toc, size);
2599  memset(node->shared_info, 0, size);
2600  node->shared_info->num_workers = pcxt->nworkers;
2601  shm_toc_insert(pcxt->toc, node->ps.plan->plan_node_id,
2602  node->shared_info);
2603 }
Instrumentation * instrument
Definition: execnodes.h:949
struct HashInstrumentation HashInstrumentation
int plan_node_id
Definition: plannodes.h:141
SharedHashInfo * shared_info
Definition: execnodes.h:2270
PlanState ps
Definition: execnodes.h:2266
Plan * plan
Definition: execnodes.h:939
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
Definition: shm_toc.c:88
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
Definition: shm_toc.c:171
#define offsetof(type, field)
Definition: c.h:662
shm_toc * toc
Definition: parallel.h:44

◆ ExecHashInitializeWorker()

void ExecHashInitializeWorker ( HashState node,
ParallelWorkerContext pwcxt 
)

Definition at line 2610 of file nodeHash.c.

References SharedHashInfo::hinstrument, HashState::hinstrument, PlanState::instrument, ParallelWorkerNumber, PlanState::plan, Plan::plan_node_id, HashState::ps, shm_toc_lookup(), and ParallelWorkerContext::toc.

Referenced by ExecParallelInitializeWorker().

2611 {
2612  SharedHashInfo *shared_info;
2613 
2614  /* don't need this if not instrumenting */
2615  if (!node->ps.instrument)
2616  return;
2617 
2618  shared_info = (SharedHashInfo *)
2619  shm_toc_lookup(pwcxt->toc, node->ps.plan->plan_node_id, false);
2620  node->hinstrument = &shared_info->hinstrument[ParallelWorkerNumber];
2621 }
Instrumentation * instrument
Definition: execnodes.h:949
int plan_node_id
Definition: plannodes.h:141
int ParallelWorkerNumber
Definition: parallel.c:109
PlanState ps
Definition: execnodes.h:2266
HashInstrumentation * hinstrument
Definition: execnodes.h:2271
HashInstrumentation hinstrument[FLEXIBLE_ARRAY_MEMBER]
Definition: execnodes.h:2257
Plan * plan
Definition: execnodes.h:939
void * shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
Definition: shm_toc.c:232

◆ ExecHashRetrieveInstrumentation()

void ExecHashRetrieveInstrumentation ( HashState node)

Definition at line 2641 of file nodeHash.c.

References SharedHashInfo::num_workers, offsetof, palloc(), and HashState::shared_info.

Referenced by ExecParallelRetrieveInstrumentation().

2642 {
2643  SharedHashInfo *shared_info = node->shared_info;
2644  size_t size;
2645 
2646  if (shared_info == NULL)
2647  return;
2648 
2649  /* Replace node->shared_info with a copy in backend-local memory. */
2650  size = offsetof(SharedHashInfo, hinstrument) +
2651  shared_info->num_workers * sizeof(HashInstrumentation);
2652  node->shared_info = palloc(size);
2653  memcpy(node->shared_info, shared_info, size);
2654 }
struct HashInstrumentation HashInstrumentation
SharedHashInfo * shared_info
Definition: execnodes.h:2270
void * palloc(Size size)
Definition: mcxt.c:949
#define offsetof(type, field)
Definition: c.h:662

◆ ExecHashTableCreate()

HashJoinTable ExecHashTableCreate ( HashState state,
List hashOperators,
List hashCollations,
bool  keepNulls 
)

Definition at line 429 of file nodeHash.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, HashJoinTableData::area, Assert, BarrierArriveAndWait(), BarrierAttach(), BarrierPhase(), HashJoinTableData::batchCxt, HashJoinTableData::batches, HashJoinTableData::buckets, ParallelHashJoinState::build_barrier, HashJoinTableData::chunks, HashJoinTableData::collations, HashJoinTableData::curbatch, HashJoinTableData::current_chunk, CurrentMemoryContext, elog, ERROR, EState::es_query_dsa, ExecChooseHashTableSize(), ExecHashBuildSkewHash(), ExecParallelHashJoinSetUpBatches(), ExecParallelHashTableAlloc(), fmgr_info(), forboth, get_op_hash_functions(), HashJoinTableData::growEnabled, ParallelHashJoinState::growth, HashJoinTableData::hashCxt, HashJoinTableData::hashStrict, i, HashJoinTableData::inner_hashfunctions, HashJoinTableData::innerBatchFile, HashJoinTableData::keepNulls, lfirst_oid, list_length(), HashJoinTableData::log2_nbuckets, HashJoinTableData::log2_nbuckets_optimal, MemoryContextSwitchTo(), my_log2(), ParallelHashJoinState::nbatch, HashJoinTableData::nbatch, HashJoinTableData::nbatch_original, HashJoinTableData::nbatch_outstart, ParallelHashJoinState::nbuckets, HashJoinTableData::nbuckets, HashJoinTableData::nbuckets_optimal, HashJoinTableData::nbuckets_original, ParallelHashJoinState::nparticipants, HashJoinTableData::nSkewBuckets, OidIsValid, op_strict(), HashJoinTableData::outer_hashfunctions, HashJoinTableData::outerBatchFile, outerPlan, palloc(), palloc0(), Plan::parallel_aware, HashJoinTableData::parallel_state, HashState::parallel_state, HashJoinTableData::partialTuples, PHJ_BUILD_ELECTING, PHJ_GROWTH_OK, Hash::plan, PlanState::plan, Plan::plan_rows, Plan::plan_width, PrepareTempTablespaces(), printf, HashState::ps, Hash::rows_total, SKEW_WORK_MEM_PERCENT, HashJoinTableData::skewBucket, HashJoinTableData::skewBucketLen, HashJoinTableData::skewBucketNums, HashJoinTableData::skewEnabled, Hash::skewTable, HashJoinTableData::skewTuples, ParallelHashJoinState::space_allowed, HashJoinTableData::spaceAllowed, HashJoinTableData::spaceAllowedSkew, HashJoinTableData::spacePeak, HashJoinTableData::spaceUsed, HashJoinTableData::spaceUsedSkew, PlanState::state, HashJoinTableData::totalTuples, HashJoinTableData::unshared, and WAIT_EVENT_HASH_BUILD_ELECTING.

Referenced by ExecHashJoinImpl().

430 {
431  Hash *node;
432  HashJoinTable hashtable;
433  Plan *outerNode;
434  size_t space_allowed;
435  int nbuckets;
436  int nbatch;
437  double rows;
438  int num_skew_mcvs;
439  int log2_nbuckets;
440  int nkeys;
441  int i;
442  ListCell *ho;
443  ListCell *hc;
444  MemoryContext oldcxt;
445 
446  /*
447  * Get information about the size of the relation to be hashed (it's the
448  * "outer" subtree of this node, but the inner relation of the hashjoin).
449  * Compute the appropriate size of the hash table.
450  */
451  node = (Hash *) state->ps.plan;
452  outerNode = outerPlan(node);
453 
454  /*
455  * If this is shared hash table with a partial plan, then we can't use
456  * outerNode->plan_rows to estimate its size. We need an estimate of the
457  * total number of rows across all copies of the partial plan.
458  */
459  rows = node->plan.parallel_aware ? node->rows_total : outerNode->plan_rows;
460 
461  ExecChooseHashTableSize(rows, outerNode->plan_width,
462  OidIsValid(node->skewTable),
463  state->parallel_state != NULL,
464  state->parallel_state != NULL ?
465  state->parallel_state->nparticipants - 1 : 0,
466  &space_allowed,
467  &nbuckets, &nbatch, &num_skew_mcvs);
468 
469  /* nbuckets must be a power of 2 */
470  log2_nbuckets = my_log2(nbuckets);
471  Assert(nbuckets == (1 << log2_nbuckets));
472 
473  /*
474  * Initialize the hash table control block.
475  *
476  * The hashtable control block is just palloc'd from the executor's
477  * per-query memory context. Everything else should be kept inside the
478  * subsidiary hashCxt or batchCxt.
479  */
480  hashtable = (HashJoinTable) palloc(sizeof(HashJoinTableData));
481  hashtable->nbuckets = nbuckets;
482  hashtable->nbuckets_original = nbuckets;
483  hashtable->nbuckets_optimal = nbuckets;
484  hashtable->log2_nbuckets = log2_nbuckets;
485  hashtable->log2_nbuckets_optimal = log2_nbuckets;
486  hashtable->buckets.unshared = NULL;
487  hashtable->keepNulls = keepNulls;
488  hashtable->skewEnabled = false;
489  hashtable->skewBucket = NULL;
490  hashtable->skewBucketLen = 0;
491  hashtable->nSkewBuckets = 0;
492  hashtable->skewBucketNums = NULL;
493  hashtable->nbatch = nbatch;
494  hashtable->curbatch = 0;
495  hashtable->nbatch_original = nbatch;
496  hashtable->nbatch_outstart = nbatch;
497  hashtable->growEnabled = true;
498  hashtable->totalTuples = 0;
499  hashtable->partialTuples = 0;
500  hashtable->skewTuples = 0;
501  hashtable->innerBatchFile = NULL;
502  hashtable->outerBatchFile = NULL;
503  hashtable->spaceUsed = 0;
504  hashtable->spacePeak = 0;
505  hashtable->spaceAllowed = space_allowed;
506  hashtable->spaceUsedSkew = 0;
507  hashtable->spaceAllowedSkew =
508  hashtable->spaceAllowed * SKEW_WORK_MEM_PERCENT / 100;
509  hashtable->chunks = NULL;
510  hashtable->current_chunk = NULL;
511  hashtable->parallel_state = state->parallel_state;
512  hashtable->area = state->ps.state->es_query_dsa;
513  hashtable->batches = NULL;
514 
515 #ifdef HJDEBUG
516  printf("Hashjoin %p: initial nbatch = %d, nbuckets = %d\n",
517  hashtable, nbatch, nbuckets);
518 #endif
519 
520  /*
521  * Create temporary memory contexts in which to keep the hashtable working
522  * storage. See notes in executor/hashjoin.h.
523  */
525  "HashTableContext",
527 
528  hashtable->batchCxt = AllocSetContextCreate(hashtable->hashCxt,
529  "HashBatchContext",
531 
532  /* Allocate data that will live for the life of the hashjoin */
533 
534  oldcxt = MemoryContextSwitchTo(hashtable->hashCxt);
535 
536  /*
537  * Get info about the hash functions to be used for each hash key. Also
538  * remember whether the join operators are strict.
539  */
540  nkeys = list_length(hashOperators);
541  hashtable->outer_hashfunctions =
542  (FmgrInfo *) palloc(nkeys * sizeof(FmgrInfo));
543  hashtable->inner_hashfunctions =
544  (FmgrInfo *) palloc(nkeys * sizeof(FmgrInfo));
545  hashtable->hashStrict = (bool *) palloc(nkeys * sizeof(bool));
546  hashtable->collations = (Oid *) palloc(nkeys * sizeof(Oid));
547  i = 0;
548  forboth(ho, hashOperators, hc, hashCollations)
549  {
550  Oid hashop = lfirst_oid(ho);
551  Oid left_hashfn;
552  Oid right_hashfn;
553 
554  if (!get_op_hash_functions(hashop, &left_hashfn, &right_hashfn))
555  elog(ERROR, "could not find hash function for hash operator %u",
556  hashop);
557  fmgr_info(left_hashfn, &hashtable->outer_hashfunctions[i]);
558  fmgr_info(right_hashfn, &hashtable->inner_hashfunctions[i]);
559  hashtable->hashStrict[i] = op_strict(hashop);
560  hashtable->collations[i] = lfirst_oid(hc);
561  i++;
562  }
563 
564  if (nbatch > 1 && hashtable->parallel_state == NULL)
565  {
566  /*
567  * allocate and initialize the file arrays in hashCxt (not needed for
568  * parallel case which uses shared tuplestores instead of raw files)
569  */
570  hashtable->innerBatchFile = (BufFile **)
571  palloc0(nbatch * sizeof(BufFile *));
572  hashtable->outerBatchFile = (BufFile **)
573  palloc0(nbatch * sizeof(BufFile *));
574  /* The files will not be opened until needed... */
575  /* ... but make sure we have temp tablespaces established for them */
577  }
578 
579  MemoryContextSwitchTo(oldcxt);
580 
581  if (hashtable->parallel_state)
582  {
583  ParallelHashJoinState *pstate = hashtable->parallel_state;
584  Barrier *build_barrier;
585 
586  /*
587  * Attach to the build barrier. The corresponding detach operation is
588  * in ExecHashTableDetach. Note that we won't attach to the
589  * batch_barrier for batch 0 yet. We'll attach later and start it out
590  * in PHJ_BATCH_PROBING phase, because batch 0 is allocated up front
591  * and then loaded while hashing (the standard hybrid hash join
592  * algorithm), and we'll coordinate that using build_barrier.
593  */
594  build_barrier = &pstate->build_barrier;
595  BarrierAttach(build_barrier);
596 
597  /*
598  * So far we have no idea whether there are any other participants,
599  * and if so, what phase they are working on. The only thing we care
600  * about at this point is whether someone has already created the
601  * SharedHashJoinBatch objects and the hash table for batch 0. One
602  * backend will be elected to do that now if necessary.
603  */
604  if (BarrierPhase(build_barrier) == PHJ_BUILD_ELECTING &&
606  {
607  pstate->nbatch = nbatch;
608  pstate->space_allowed = space_allowed;
609  pstate->growth = PHJ_GROWTH_OK;
610 
611  /* Set up the shared state for coordinating batches. */
612  ExecParallelHashJoinSetUpBatches(hashtable, nbatch);
613 
614  /*
615  * Allocate batch 0's hash table up front so we can load it
616  * directly while hashing.
617  */
618  pstate->nbuckets = nbuckets;
619  ExecParallelHashTableAlloc(hashtable, 0);
620  }
621 
622  /*
623  * The next Parallel Hash synchronization point is in
624  * MultiExecParallelHash(), which will progress it all the way to
625  * PHJ_BUILD_DONE. The caller must not return control from this
626  * executor node between now and then.
627  */
628  }
629  else
630  {
631  /*
632  * Prepare context for the first-scan space allocations; allocate the
633  * hashbucket array therein, and set each bucket "empty".
634  */
635  MemoryContextSwitchTo(hashtable->batchCxt);
636 
637  hashtable->buckets.unshared = (HashJoinTuple *)
638  palloc0(nbuckets * sizeof(HashJoinTuple));
639 
640  /*
641  * Set up for skew optimization, if possible and there's a need for
642  * more than one batch. (In a one-batch join, there's no point in
643  * it.)
644  */
645  if (nbatch > 1)
646  ExecHashBuildSkewHash(hashtable, node, num_skew_mcvs);
647 
648  MemoryContextSwitchTo(oldcxt);
649  }
650 
651  return hashtable;
652 }
int log2_nbuckets_optimal
Definition: hashjoin.h:291
double rows_total
Definition: plannodes.h:924
Oid skewTable
Definition: plannodes.h:920
struct ParallelHashJoinState * parallel_state
Definition: execnodes.h:2274
double skewTuples
Definition: hashjoin.h:320
Definition: fmgr.h:56
struct dsa_area * es_query_dsa
Definition: execnodes.h:583
double plan_rows
Definition: plannodes.h:129
bool op_strict(Oid opno)
Definition: lsyscache.c:1279
#define AllocSetContextCreate
Definition: memutils.h:170
bool get_op_hash_functions(Oid opno, RegProcedure *lhs_procno, RegProcedure *rhs_procno)
Definition: lsyscache.c:507
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:419
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define printf(...)
Definition: port.h:198
FmgrInfo * inner_hashfunctions
Definition: hashjoin.h:338
void ExecParallelHashTableAlloc(HashJoinTable hashtable, int batchno)
Definition: nodeHash.c:3064
EState * state
Definition: execnodes.h:941
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:645
static void ExecHashBuildSkewHash(HashJoinTable hashtable, Hash *node, int mcvsToUse)
Definition: nodeHash.c:2209
double partialTuples
Definition: hashjoin.h:319
dsa_area * area
Definition: hashjoin.h:356
int * skewBucketNums
Definition: hashjoin.h:308
#define ERROR
Definition: elog.h:43
void PrepareTempTablespaces(void)
Definition: tablespace.c:1323
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:124
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
BufFile ** outerBatchFile
Definition: hashjoin.h:330
Size spaceAllowedSkew
Definition: hashjoin.h:346
bool parallel_aware
Definition: plannodes.h:135
PlanState ps
Definition: execnodes.h:2266
#define PHJ_BUILD_ELECTING
Definition: hashjoin.h:257
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
MemoryContext batchCxt
Definition: hashjoin.h:349
struct HashJoinTableData * HashJoinTable
Definition: execnodes.h:1924
int my_log2(long num)
Definition: dynahash.c:1718
#define outerPlan(node)
Definition: plannodes.h:172
FmgrInfo * outer_hashfunctions
Definition: hashjoin.h:337
HashSkewBucket ** skewBucket
Definition: hashjoin.h:305
int BarrierAttach(Barrier *barrier)
Definition: barrier.c:214
void * palloc0(Size size)
Definition: mcxt.c:980
ParallelHashJoinState * parallel_state
Definition: hashjoin.h:357
ParallelHashJoinBatchAccessor * batches
Definition: hashjoin.h:358
Plan * plan
Definition: execnodes.h:939
double totalTuples
Definition: hashjoin.h:318
int plan_width
Definition: plannodes.h:130
#define Assert(condition)
Definition: c.h:739
ParallelHashGrowth growth
Definition: hashjoin.h:241
BufFile ** innerBatchFile
Definition: hashjoin.h:329
static int list_length(const List *l)
Definition: pg_list.h:169
int BarrierPhase(Barrier *barrier)
Definition: barrier.c:243
union HashJoinTableData::@97 buckets
bool BarrierArriveAndWait(Barrier *barrier, uint32 wait_event_info)
Definition: barrier.c:125
HashMemoryChunk chunks
Definition: hashjoin.h:352
Plan plan
Definition: plannodes.h:913
void * palloc(Size size)
Definition: mcxt.c:949
static void ExecParallelHashJoinSetUpBatches(HashJoinTable hashtable, int nbatch)
Definition: nodeHash.c:2903
struct HashJoinTupleData ** unshared
Definition: hashjoin.h:297
HashMemoryChunk current_chunk
Definition: hashjoin.h:355
#define elog(elevel,...)
Definition: elog.h:228
int i
bool * hashStrict
Definition: hashjoin.h:339
MemoryContext hashCxt
Definition: hashjoin.h:348
#define SKEW_WORK_MEM_PERCENT
Definition: hashjoin.h:110
void ExecChooseHashTableSize(double ntuples, int tupwidth, bool useskew, bool try_combined_work_mem, int parallel_workers, size_t *space_allowed, int *numbuckets, int *numbatches, int *num_skew_mcvs)
Definition: nodeHash.c:666
#define lfirst_oid(lc)
Definition: pg_list.h:192

◆ ExecHashTableDestroy()

void ExecHashTableDestroy ( HashJoinTable  hashtable)

Definition at line 853 of file nodeHash.c.

References BufFileClose(), HashJoinTableData::hashCxt, i, HashJoinTableData::innerBatchFile, MemoryContextDelete(), HashJoinTableData::nbatch, HashJoinTableData::outerBatchFile, and pfree().

Referenced by ExecEndHashJoin(), and ExecReScanHashJoin().

854 {
855  int i;
856 
857  /*
858  * Make sure all the temp files are closed. We skip batch 0, since it
859  * can't have any temp files (and the arrays might not even exist if
860  * nbatch is only 1). Parallel hash joins don't use these files.
861  */
862  if (hashtable->innerBatchFile != NULL)
863  {
864  for (i = 1; i < hashtable->nbatch; i++)
865  {
866  if (hashtable->innerBatchFile[i])
867  BufFileClose(hashtable->innerBatchFile[i]);
868  if (hashtable->outerBatchFile[i])
869  BufFileClose(hashtable->outerBatchFile[i]);
870  }
871  }
872 
873  /* Release working memory (batchCxt is a child, so it goes away too) */
874  MemoryContextDelete(hashtable->hashCxt);
875 
876  /* And drop the control block */
877  pfree(hashtable);
878 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
void BufFileClose(BufFile *file)
Definition: buffile.c:391
void pfree(void *pointer)
Definition: mcxt.c:1056
BufFile ** outerBatchFile
Definition: hashjoin.h:330
BufFile ** innerBatchFile
Definition: hashjoin.h:329
int i
MemoryContext hashCxt
Definition: hashjoin.h:348

◆ ExecHashTableDetach()

void ExecHashTableDetach ( HashJoinTable  hashtable)

Definition at line 3141 of file nodeHash.c.

References HashJoinTableData::area, BarrierDetach(), ParallelHashJoinState::batches, HashJoinTableData::batches, ParallelHashJoinState::build_barrier, dsa_free(), DsaPointerIsValid, i, ParallelHashJoinBatchAccessor::inner_tuples, InvalidDsaPointer, HashJoinTableData::nbatch, ParallelHashJoinBatchAccessor::outer_tuples, HashJoinTableData::parallel_state, sts_end_parallel_scan(), and sts_end_write().

Referenced by ExecHashJoinReInitializeDSM(), and ExecShutdownHashJoin().

3142 {
3143  if (hashtable->parallel_state)
3144  {
3145  ParallelHashJoinState *pstate = hashtable->parallel_state;
3146  int i;
3147 
3148  /* Make sure any temporary files are closed. */
3149  if (hashtable->batches)
3150  {
3151  for (i = 0; i < hashtable->nbatch; ++i)
3152  {
3153  sts_end_write(hashtable->batches[i].inner_tuples);
3154  sts_end_write(hashtable->batches[i].outer_tuples);
3157  }
3158  }
3159 
3160  /* If we're last to detach, clean up shared memory. */
3161  if (BarrierDetach(&pstate->build_barrier))
3162  {
3163  if (DsaPointerIsValid(pstate->batches))
3164  {
3165  dsa_free(hashtable->area, pstate->batches);
3166  pstate->batches = InvalidDsaPointer;
3167  }
3168  }
3169 
3170  hashtable->parallel_state = NULL;
3171  }
3172 }
SharedTuplestoreAccessor * outer_tuples
Definition: hashjoin.h:209
#define InvalidDsaPointer
Definition: dsa.h:78
SharedTuplestoreAccessor * inner_tuples
Definition: hashjoin.h:208
dsa_area * area
Definition: hashjoin.h:356
dsa_pointer batches
Definition: hashjoin.h:236
void sts_end_parallel_scan(SharedTuplestoreAccessor *accessor)
ParallelHashJoinState * parallel_state
Definition: hashjoin.h:357
ParallelHashJoinBatchAccessor * batches
Definition: hashjoin.h:358
bool BarrierDetach(Barrier *barrier)
Definition: barrier.c:234
#define DsaPointerIsValid(x)
Definition: dsa.h:81
void dsa_free(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:820
int i
void sts_end_write(SharedTuplestoreAccessor *accessor)

◆ ExecHashTableDetachBatch()

void ExecHashTableDetachBatch ( HashJoinTable  hashtable)

Definition at line 3084 of file nodeHash.c.

References HashJoinTableData::area, Assert, BarrierArriveAndDetach(), BarrierPhase(), ParallelHashJoinBatch::batch_barrier, HashJoinTableData::batches, ParallelHashJoinBatch::buckets, ParallelHashJoinBatch::chunks, HashJoinTableData::curbatch, dsa_free(), dsa_get_address(), DsaPointerIsValid, ParallelHashJoinBatchAccessor::inner_tuples, InvalidDsaPointer, Max, HashJoinTableData::nbuckets, HashMemoryChunkData::next, next, ParallelHashJoinBatchAccessor::outer_tuples, HashJoinTableData::parallel_state, PHJ_BATCH_DONE, HashMemoryChunkData::shared, ParallelHashJoinBatchAccessor::shared, ParallelHashJoinBatch::size, HashJoinTableData::spacePeak, and sts_end_parallel_scan().

Referenced by ExecHashJoinReInitializeDSM(), ExecParallelHashJoinNewBatch(), and ExecShutdownHashJoin().

3085 {
3086  if (hashtable->parallel_state != NULL &&
3087  hashtable->curbatch >= 0)
3088  {
3089  int curbatch = hashtable->curbatch;
3090  ParallelHashJoinBatch *batch = hashtable->batches[curbatch].shared;
3091 
3092  /* Make sure any temporary files are closed. */
3093  sts_end_parallel_scan(hashtable->batches[curbatch].inner_tuples);
3094  sts_end_parallel_scan(hashtable->batches[curbatch].outer_tuples);
3095 
3096  /* Detach from the batch we were last working on. */
3098  {
3099  /*
3100  * Technically we shouldn't access the barrier because we're no
3101  * longer attached, but since there is no way it's moving after
3102  * this point it seems safe to make the following assertion.
3103  */
3105 
3106  /* Free shared chunks and buckets. */
3107  while (DsaPointerIsValid(batch->chunks))
3108  {
3109  HashMemoryChunk chunk =
3110  dsa_get_address(hashtable->area, batch->chunks);
3111  dsa_pointer next = chunk->next.shared;
3112 
3113  dsa_free(hashtable->area, batch->chunks);
3114  batch->chunks = next;
3115  }
3116  if (DsaPointerIsValid(batch->buckets))
3117  {
3118  dsa_free(hashtable->area, batch->buckets);
3119  batch->buckets = InvalidDsaPointer;
3120  }
3121  }
3122 
3123  /*
3124  * Track the largest batch we've been attached to. Though each
3125  * backend might see a different subset of batches, explain.c will
3126  * scan the results from all backends to find the largest value.
3127  */
3128  hashtable->spacePeak =
3129  Max(hashtable->spacePeak,
3130  batch->size + sizeof(dsa_pointer_atomic) * hashtable->nbuckets);
3131 
3132  /* Remember that we are not attached to a batch. */
3133  hashtable->curbatch = -1;
3134  }
3135 }
SharedTuplestoreAccessor * outer_tuples
Definition: hashjoin.h:209
#define PHJ_BATCH_DONE
Definition: hashjoin.h:268
static int32 next
Definition: blutils.c:213
#define InvalidDsaPointer
Definition: dsa.h:78
dsa_pointer chunks
Definition: hashjoin.h:156
uint64 dsa_pointer
Definition: dsa.h:62
SharedTuplestoreAccessor * inner_tuples
Definition: hashjoin.h:208
dsa_area * area
Definition: hashjoin.h:356
dsa_pointer shared
Definition: hashjoin.h:127
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:932
union HashMemoryChunkData::@96 next
void sts_end_parallel_scan(SharedTuplestoreAccessor *accessor)
bool BarrierArriveAndDetach(Barrier *barrier)
Definition: barrier.c:203
ParallelHashJoinState * parallel_state
Definition: hashjoin.h:357
ParallelHashJoinBatchAccessor * batches
Definition: hashjoin.h:358
#define Max(x, y)
Definition: c.h:905
#define Assert(condition)
Definition: c.h:739
int BarrierPhase(Barrier *barrier)
Definition: barrier.c:243
ParallelHashJoinBatch * shared
Definition: hashjoin.h:197
#define DsaPointerIsValid(x)
Definition: dsa.h:81
void dsa_free(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:820
dsa_pointer buckets
Definition: hashjoin.h:153

◆ ExecHashTableInsert()

void ExecHashTableInsert ( HashJoinTable  hashtable,
TupleTableSlot slot,
uint32  hashvalue 
)

Definition at line 1593 of file nodeHash.c.

References Assert, HashJoinTableData::buckets, HashJoinTableData::curbatch, dense_alloc(), ExecFetchSlotMinimalTuple(), ExecHashGetBucketAndBatch(), ExecHashIncreaseNumBatches(), ExecHashJoinSaveTuple(), HashJoinTupleData::hashvalue, heap_free_minimal_tuple(), HeapTupleHeaderClearMatch, HJTUPLE_MINTUPLE, HJTUPLE_OVERHEAD, HashJoinTableData::innerBatchFile, HashJoinTableData::log2_nbuckets_optimal, MaxAllocSize, HashJoinTableData::nbatch, HashJoinTableData::nbuckets_optimal, HashJoinTupleData::next, NTUP_PER_BUCKET, HashJoinTableData::skewTuples, HashJoinTableData::spaceAllowed, HashJoinTableData::spacePeak, HashJoinTableData::spaceUsed, MinimalTupleData::t_len, HashJoinTableData::totalTuples, HashJoinTupleData::unshared, and HashJoinTableData::unshared.

Referenced by ExecHashJoinNewBatch(), and MultiExecPrivateHash().

1596 {
1597  bool shouldFree;
1598  MinimalTuple tuple = ExecFetchSlotMinimalTuple(slot, &shouldFree);
1599  int bucketno;
1600  int batchno;
1601 
1602  ExecHashGetBucketAndBatch(hashtable, hashvalue,
1603  &bucketno, &batchno);
1604 
1605  /*
1606  * decide whether to put the tuple in the hash table or a temp file
1607  */
1608  if (batchno == hashtable->curbatch)
1609  {
1610  /*
1611  * put the tuple in hash table
1612  */
1613  HashJoinTuple hashTuple;
1614  int hashTupleSize;
1615  double ntuples = (hashtable->totalTuples - hashtable->skewTuples);
1616 
1617  /* Create the HashJoinTuple */
1618  hashTupleSize = HJTUPLE_OVERHEAD + tuple->t_len;
1619  hashTuple = (HashJoinTuple) dense_alloc(hashtable, hashTupleSize);
1620 
1621  hashTuple->hashvalue = hashvalue;
1622  memcpy(HJTUPLE_MINTUPLE(hashTuple), tuple, tuple->t_len);
1623 
1624  /*
1625  * We always reset the tuple-matched flag on insertion. This is okay
1626  * even when reloading a tuple from a batch file, since the tuple
1627  * could not possibly have been matched to an outer tuple before it
1628  * went into the batch file.
1629  */
1631 
1632  /* Push it onto the front of the bucket's list */
1633  hashTuple->next.unshared = hashtable->buckets.unshared[bucketno];
1634  hashtable->buckets.unshared[bucketno] = hashTuple;
1635 
1636  /*
1637  * Increase the (optimal) number of buckets if we just exceeded the
1638  * NTUP_PER_BUCKET threshold, but only when there's still a single
1639  * batch.
1640  */
1641  if (hashtable->nbatch == 1 &&
1642  ntuples > (hashtable->nbuckets_optimal * NTUP_PER_BUCKET))
1643  {
1644  /* Guard against integer overflow and alloc size overflow */
1645  if (hashtable->nbuckets_optimal <= INT_MAX / 2 &&
1646  hashtable->nbuckets_optimal * 2 <= MaxAllocSize / sizeof(HashJoinTuple))
1647  {
1648  hashtable->nbuckets_optimal *= 2;
1649  hashtable->log2_nbuckets_optimal += 1;
1650  }
1651  }
1652 
1653  /* Account for space used, and back off if we've used too much */
1654  hashtable->spaceUsed += hashTupleSize;
1655  if (hashtable->spaceUsed > hashtable->spacePeak)
1656  hashtable->spacePeak = hashtable->spaceUsed;
1657  if (hashtable->spaceUsed +
1658  hashtable->nbuckets_optimal * sizeof(HashJoinTuple)
1659  > hashtable->spaceAllowed)
1660  ExecHashIncreaseNumBatches(hashtable);
1661  }
1662  else
1663  {
1664  /*
1665  * put the tuple into a temp file for later batches
1666  */
1667  Assert(batchno > hashtable->curbatch);
1668  ExecHashJoinSaveTuple(tuple,
1669  hashvalue,
1670  &hashtable->innerBatchFile[batchno]);
1671  }
1672 
1673  if (shouldFree)
1674  heap_free_minimal_tuple(tuple);
1675 }
int log2_nbuckets_optimal
Definition: hashjoin.h:291
double skewTuples
Definition: hashjoin.h:320
union HashJoinTupleData::@95 next
MinimalTuple ExecFetchSlotMinimalTuple(TupleTableSlot *slot, bool *shouldFree)
Definition: execTuples.c:1662
static void ExecHashIncreaseNumBatches(HashJoinTable hashtable)
Definition: nodeHash.c:886
void ExecHashGetBucketAndBatch(HashJoinTable hashtable, uint32 hashvalue, int *bucketno, int *batchno)
Definition: nodeHash.c:1895
struct HashJoinTupleData * unshared
Definition: hashjoin.h:72
void heap_free_minimal_tuple(MinimalTuple mtup)
Definition: heaptuple.c:1427
struct HashJoinTupleData * HashJoinTuple
Definition: execnodes.h:1923
#define MaxAllocSize
Definition: memutils.h:40
static void * dense_alloc(HashJoinTable hashtable, Size size)
Definition: nodeHash.c:2675
#define NTUP_PER_BUCKET
Definition: nodeHash.c:663
#define HJTUPLE_OVERHEAD
Definition: hashjoin.h:79
double totalTuples
Definition: hashjoin.h:318
#define HJTUPLE_MINTUPLE(hjtup)
Definition: hashjoin.h:80
#define Assert(condition)
Definition: c.h:739
BufFile ** innerBatchFile
Definition: hashjoin.h:329
#define HeapTupleHeaderClearMatch(tup)
Definition: htup_details.h:526
union HashJoinTableData::@97 buckets
struct HashJoinTupleData ** unshared
Definition: hashjoin.h:297
void ExecHashJoinSaveTuple(MinimalTuple tuple, uint32 hashvalue, BufFile **fileptr)
uint32 hashvalue
Definition: hashjoin.h:75

◆ ExecHashTableReset()

void ExecHashTableReset ( HashJoinTable  hashtable)

Definition at line 2134 of file nodeHash.c.

References HashJoinTableData::batchCxt, HashJoinTableData::buckets, HashJoinTableData::chunks, MemoryContextReset(), MemoryContextSwitchTo(), HashJoinTableData::nbuckets, palloc0(), HashJoinTableData::spaceUsed, and HashJoinTableData::unshared.

Referenced by ExecHashJoinNewBatch().

2135 {
2136  MemoryContext oldcxt;
2137  int nbuckets = hashtable->nbuckets;
2138 
2139  /*
2140  * Release all the hash buckets and tuples acquired in the prior pass, and
2141  * reinitialize the context for a new pass.
2142  */
2143  MemoryContextReset(hashtable->batchCxt);
2144  oldcxt = MemoryContextSwitchTo(hashtable->batchCxt);
2145 
2146  /* Reallocate and reinitialize the hash bucket headers. */
2147  hashtable->buckets.unshared = (HashJoinTuple *)
2148  palloc0(nbuckets * sizeof(HashJoinTuple));
2149 
2150  hashtable->spaceUsed = 0;
2151 
2152  MemoryContextSwitchTo(oldcxt);
2153 
2154  /* Forget the chunks (the memory was freed by the context reset above). */
2155  hashtable->chunks = NULL;
2156 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:136
MemoryContext batchCxt
Definition: hashjoin.h:349
void * palloc0(Size size)
Definition: mcxt.c:980
union HashJoinTableData::@97 buckets
HashMemoryChunk chunks
Definition: hashjoin.h:352
struct HashJoinTupleData ** unshared
Definition: hashjoin.h:297

◆ ExecHashTableResetMatchFlags()

void ExecHashTableResetMatchFlags ( HashJoinTable  hashtable)

Definition at line 2163 of file nodeHash.c.

References HashJoinTableData::buckets, HeapTupleHeaderClearMatch, HJTUPLE_MINTUPLE, i, HashJoinTableData::nbuckets, HashJoinTupleData::next, HashJoinTableData::nSkewBuckets, HashJoinTableData::skewBucket, HashJoinTableData::skewBucketNums, HashSkewBucket::tuples, HashJoinTupleData::unshared, and HashJoinTableData::unshared.

Referenced by ExecReScanHashJoin().

2164 {
2165  HashJoinTuple tuple;
2166  int i;
2167 
2168  /* Reset all flags in the main table ... */
2169  for (i = 0; i < hashtable->nbuckets; i++)
2170  {
2171  for (tuple = hashtable->buckets.unshared[i]; tuple != NULL;
2172  tuple = tuple->next.unshared)
2174  }
2175 
2176  /* ... and the same for the skew buckets, if any */
2177  for (i = 0; i < hashtable->nSkewBuckets; i++)
2178  {
2179  int j = hashtable->skewBucketNums[i];
2180  HashSkewBucket *skewBucket = hashtable->skewBucket[j];
2181 
2182  for (tuple = skewBucket->tuples; tuple != NULL; tuple = tuple->next.unshared)
2184  }
2185 }
union HashJoinTupleData::@95 next
int * skewBucketNums
Definition: hashjoin.h:308
struct HashJoinTupleData * unshared
Definition: hashjoin.h:72
HashJoinTuple tuples
Definition: hashjoin.h:105
HashSkewBucket ** skewBucket
Definition: hashjoin.h:305
#define HJTUPLE_MINTUPLE(hjtup)
Definition: hashjoin.h:80
#define HeapTupleHeaderClearMatch(tup)
Definition: htup_details.h:526
union HashJoinTableData::@97 buckets
struct HashJoinTupleData ** unshared
Definition: hashjoin.h:297
int i

◆ ExecInitHash()

HashState* ExecInitHash ( Hash node,
EState estate,
int  eflags 
)

Definition at line 352 of file nodeHash.c.

References Assert, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, ExecAssignExprContext(), ExecHash(), ExecInitExprList(), ExecInitNode(), ExecInitResultTupleSlotTL(), PlanState::ExecProcNode, Hash::hashkeys, HashState::hashkeys, HashState::hashtable, makeNode, NIL, outerPlan, outerPlanState, Hash::plan, PlanState::plan, HashState::ps, PlanState::ps_ProjInfo, Plan::qual, PlanState::state, and TTSOpsMinimalTuple.

Referenced by ExecInitNode().

353 {
354  HashState *hashstate;
355 
356  /* check for unsupported flags */
357  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
358 
359  /*
360  * create state structure
361  */
362  hashstate = makeNode(HashState);
363  hashstate->ps.plan = (Plan *) node;
364  hashstate->ps.state = estate;
365  hashstate->ps.ExecProcNode = ExecHash;
366  hashstate->hashtable = NULL;
367  hashstate->hashkeys = NIL; /* will be set by parent HashJoin */
368 
369  /*
370  * Miscellaneous initialization
371  *
372  * create expression context for node
373  */
374  ExecAssignExprContext(estate, &hashstate->ps);
375 
376  /*
377  * initialize child nodes
378  */
379  outerPlanState(hashstate) = ExecInitNode(outerPlan(node), estate, eflags);
380 
381  /*
382  * initialize our result slot and type. No need to build projection
383  * because this node doesn't do projections.
384  */
386  hashstate->ps.ps_ProjInfo = NULL;
387 
388  /*
389  * initialize child expressions
390  */
391  Assert(node->plan.qual == NIL);
392  hashstate->hashkeys =
393  ExecInitExprList(node->hashkeys, (PlanState *) hashstate);
394 
395  return hashstate;
396 }
#define NIL
Definition: pg_list.h:65
List * qual
Definition: plannodes.h:143
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:979
HashJoinTable hashtable
Definition: execnodes.h:2267
EState * state
Definition: execnodes.h:941
#define EXEC_FLAG_BACKWARD
Definition: executor.h:58
#define outerPlanState(node)
Definition: execnodes.h:1033
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:316
List * hashkeys
Definition: execnodes.h:2268
PlanState ps
Definition: execnodes.h:2266
#define outerPlan(node)
Definition: plannodes.h:172
static TupleTableSlot * ExecHash(PlanState *pstate)
Definition: nodeHash.c:90
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:945
List * hashkeys
Definition: plannodes.h:919
Plan * plan
Definition: execnodes.h:939
#define makeNode(_type_)
Definition: nodes.h:573
#define Assert(condition)
Definition: c.h:739
#define EXEC_FLAG_MARK
Definition: executor.h:59
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:444
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1769
Plan plan
Definition: plannodes.h:913
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:138
const TupleTableSlotOps TTSOpsMinimalTuple
Definition: execTuples.c:85

◆ ExecParallelHashTableAlloc()

void ExecParallelHashTableAlloc ( HashJoinTable  hashtable,
int  batchno 
)

Definition at line 3064 of file nodeHash.c.

References HashJoinTableData::area, HashJoinTableData::batches, ParallelHashJoinBatch::buckets, dsa_allocate, dsa_get_address(), dsa_pointer_atomic_init, i, InvalidDsaPointer, ParallelHashJoinState::nbuckets, HashJoinTableData::parallel_state, and ParallelHashJoinBatchAccessor::shared.

Referenced by ExecHashTableCreate(), and ExecParallelHashJoinNewBatch().

3065 {
3066  ParallelHashJoinBatch *batch = hashtable->batches[batchno].shared;
3067  dsa_pointer_atomic *buckets;
3068  int nbuckets = hashtable->parallel_state->nbuckets;
3069  int i;
3070 
3071  batch->buckets =
3072  dsa_allocate(hashtable->area, sizeof(dsa_pointer_atomic) * nbuckets);
3073  buckets = (dsa_pointer_atomic *)
3074  dsa_get_address(hashtable->area, batch->buckets);
3075  for (i = 0; i < nbuckets; ++i)
3077 }
#define InvalidDsaPointer
Definition: dsa.h:78
dsa_area * area
Definition: hashjoin.h:356
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:932
ParallelHashJoinState * parallel_state
Definition: hashjoin.h:357
ParallelHashJoinBatchAccessor * batches
Definition: hashjoin.h:358
ParallelHashJoinBatch * shared
Definition: hashjoin.h:197
#define dsa_pointer_atomic_init
Definition: dsa.h:64
int i
#define dsa_allocate(area, size)
Definition: dsa.h:84
dsa_pointer buckets
Definition: hashjoin.h:153

◆ ExecParallelHashTableInsert()

void ExecParallelHashTableInsert ( HashJoinTable  hashtable,
TupleTableSlot slot,
uint32  hashvalue 
)

Definition at line 1682 of file nodeHash.c.

References Assert, BarrierPhase(), HashJoinTableData::batches, HashJoinTableData::buckets, ParallelHashJoinState::build_barrier, ExecFetchSlotMinimalTuple(), ExecHashGetBucketAndBatch(), ExecParallelHashPushTuple(), ExecParallelHashTupleAlloc(), ExecParallelHashTuplePrealloc(), HashJoinTupleData::hashvalue, heap_free_minimal_tuple(), HJTUPLE_MINTUPLE, HJTUPLE_OVERHEAD, ParallelHashJoinBatchAccessor::inner_tuples, MAXALIGN, ParallelHashJoinBatchAccessor::ntuples, HashJoinTableData::parallel_state, PHJ_BUILD_HASHING_INNER, ParallelHashJoinBatchAccessor::preallocated, HashJoinTableData::shared, sts_puttuple(), and MinimalTupleData::t_len.

Referenced by MultiExecParallelHash().

1685 {
1686  bool shouldFree;
1687  MinimalTuple tuple = ExecFetchSlotMinimalTuple(slot, &shouldFree);
1688  dsa_pointer shared;
1689  int bucketno;
1690  int batchno;
1691 
1692 retry:
1693  ExecHashGetBucketAndBatch(hashtable, hashvalue, &bucketno, &batchno);
1694 
1695  if (batchno == 0)
1696  {
1697  HashJoinTuple hashTuple;
1698 
1699  /* Try to load it into memory. */
1702  hashTuple = ExecParallelHashTupleAlloc(hashtable,
1703  HJTUPLE_OVERHEAD + tuple->t_len,
1704  &shared);
1705  if (hashTuple == NULL)
1706  goto retry;
1707 
1708  /* Store the hash value in the HashJoinTuple header. */
1709  hashTuple->hashvalue = hashvalue;
1710  memcpy(HJTUPLE_MINTUPLE(hashTuple), tuple, tuple->t_len);
1711 
1712  /* Push it onto the front of the bucket's list */
1713  ExecParallelHashPushTuple(&hashtable->buckets.shared[bucketno],
1714  hashTuple, shared);
1715  }
1716  else
1717  {
1718  size_t tuple_size = MAXALIGN(HJTUPLE_OVERHEAD + tuple->t_len);
1719 
1720  Assert(batchno > 0);
1721 
1722  /* Try to preallocate space in the batch if necessary. */
1723  if (hashtable->batches[batchno].preallocated < tuple_size)
1724  {
1725  if (!ExecParallelHashTuplePrealloc(hashtable, batchno, tuple_size))
1726  goto retry;
1727  }
1728 
1729  Assert(hashtable->batches[batchno].preallocated >= tuple_size);
1730  hashtable->batches[batchno].preallocated -= tuple_size;
1731  sts_puttuple(hashtable->batches[batchno].inner_tuples, &hashvalue,
1732  tuple);
1733  }
1734  ++hashtable->batches[batchno].ntuples;
1735 
1736  if (shouldFree)
1737  heap_free_minimal_tuple(tuple);
1738 }
dsa_pointer_atomic * shared
Definition: hashjoin.h:299
void sts_puttuple(SharedTuplestoreAccessor *accessor, void *meta_data, MinimalTuple tuple)
MinimalTuple ExecFetchSlotMinimalTuple(TupleTableSlot *slot, bool *shouldFree)
Definition: execTuples.c:1662
uint64 dsa_pointer
Definition: dsa.h:62
SharedTuplestoreAccessor * inner_tuples
Definition: hashjoin.h:208
void ExecHashGetBucketAndBatch(HashJoinTable hashtable, uint32 hashvalue, int *bucketno, int *batchno)
Definition: nodeHash.c:1895
void heap_free_minimal_tuple(MinimalTuple mtup)
Definition: heaptuple.c:1427
static bool ExecParallelHashTuplePrealloc(HashJoinTable hashtable, int batchno, size_t size)
Definition: nodeHash.c:3288
ParallelHashJoinState * parallel_state
Definition: hashjoin.h:357
#define HJTUPLE_OVERHEAD
Definition: hashjoin.h:79
ParallelHashJoinBatchAccessor * batches
Definition: hashjoin.h:358
#define HJTUPLE_MINTUPLE(hjtup)
Definition: hashjoin.h:80
#define Assert(condition)
Definition: c.h:739
int BarrierPhase(Barrier *barrier)
Definition: barrier.c:243
#define MAXALIGN(LEN)
Definition: c.h:692
union HashJoinTableData::@97 buckets
static void ExecParallelHashPushTuple(dsa_pointer_atomic *head, HashJoinTuple tuple, dsa_pointer tuple_shared)
Definition: nodeHash.c:3208
#define PHJ_BUILD_HASHING_INNER
Definition: hashjoin.h:259
static HashJoinTuple ExecParallelHashTupleAlloc(HashJoinTable hashtable, size_t size, dsa_pointer *shared)
Definition: nodeHash.c:2755
uint32 hashvalue
Definition: hashjoin.h:75

◆ ExecParallelHashTableInsertCurrentBatch()

void ExecParallelHashTableInsertCurrentBatch ( HashJoinTable  hashtable,
TupleTableSlot slot,
uint32  hashvalue 
)

Definition at line 1747 of file nodeHash.c.

References Assert, HashJoinTableData::buckets, HashJoinTableData::curbatch, ExecFetchSlotMinimalTuple(), ExecHashGetBucketAndBatch(), ExecParallelHashPushTuple(), ExecParallelHashTupleAlloc(), HashJoinTupleData::hashvalue, heap_free_minimal_tuple(), HeapTupleHeaderClearMatch, HJTUPLE_MINTUPLE, HJTUPLE_OVERHEAD, HashJoinTableData::shared, and MinimalTupleData::t_len.

Referenced by ExecParallelHashJoinNewBatch().

1750 {
1751  bool shouldFree;
1752  MinimalTuple tuple = ExecFetchSlotMinimalTuple(slot, &shouldFree);
1753  HashJoinTuple hashTuple;
1754  dsa_pointer shared;
1755  int batchno;
1756  int bucketno;
1757 
1758  ExecHashGetBucketAndBatch(hashtable, hashvalue, &bucketno, &batchno);
1759  Assert(batchno == hashtable->curbatch);
1760  hashTuple = ExecParallelHashTupleAlloc(hashtable,
1761  HJTUPLE_OVERHEAD + tuple->t_len,
1762  &shared);
1763  hashTuple->hashvalue = hashvalue;
1764  memcpy(HJTUPLE_MINTUPLE(hashTuple), tuple, tuple->t_len);
1766  ExecParallelHashPushTuple(&hashtable->buckets.shared[bucketno],
1767  hashTuple, shared);
1768 
1769  if (shouldFree)
1770  heap_free_minimal_tuple(tuple);
1771 }
dsa_pointer_atomic * shared
Definition: hashjoin.h:299
MinimalTuple ExecFetchSlotMinimalTuple(TupleTableSlot *slot, bool *shouldFree)
Definition: execTuples.c:1662
uint64 dsa_pointer
Definition: dsa.h:62
void ExecHashGetBucketAndBatch(HashJoinTable hashtable, uint32 hashvalue, int *bucketno, int *batchno)
Definition: nodeHash.c:1895
void heap_free_minimal_tuple(MinimalTuple mtup)
Definition: heaptuple.c:1427
#define HJTUPLE_OVERHEAD
Definition: hashjoin.h:79
#define HJTUPLE_MINTUPLE(hjtup)
Definition: hashjoin.h:80
#define Assert(condition)
Definition: c.h:739
#define HeapTupleHeaderClearMatch(tup)
Definition: htup_details.h:526
union HashJoinTableData::@97 buckets
static void ExecParallelHashPushTuple(dsa_pointer_atomic *head, HashJoinTuple tuple, dsa_pointer tuple_shared)
Definition: nodeHash.c:3208
static HashJoinTuple ExecParallelHashTupleAlloc(HashJoinTable hashtable, size_t size, dsa_pointer *shared)
Definition: nodeHash.c:2755
uint32 hashvalue
Definition: hashjoin.h:75

◆ ExecParallelHashTableSetCurrentBatch()

void ExecParallelHashTableSetCurrentBatch ( HashJoinTable  hashtable,
int  batchno 
)

Definition at line 3226 of file nodeHash.c.

References HashJoinTableData::area, Assert, ParallelHashJoinBatchAccessor::at_least_one_chunk, HashJoinTableData::batches, ParallelHashJoinBatch::buckets, HashJoinTableData::buckets, HashJoinTableData::curbatch, HashJoinTableData::current_chunk, HashJoinTableData::current_chunk_shared, dsa_get_address(), InvalidDsaPointer, HashJoinTableData::log2_nbuckets, my_log2(), ParallelHashJoinState::nbuckets, HashJoinTableData::nbuckets, HashJoinTableData::parallel_state, ParallelHashJoinBatchAccessor::shared, and HashJoinTableData::shared.

Referenced by ExecParallelHashIncreaseNumBatches(), ExecParallelHashIncreaseNumBuckets(), ExecParallelHashJoinNewBatch(), and MultiExecParallelHash().

3227 {
3228  Assert(hashtable->batches[batchno].shared->buckets != InvalidDsaPointer);
3229 
3230  hashtable->curbatch = batchno;
3231  hashtable->buckets.shared = (dsa_pointer_atomic *)
3232  dsa_get_address(hashtable->area,
3233  hashtable->batches[batchno].shared->buckets);
3234  hashtable->nbuckets = hashtable->parallel_state->nbuckets;
3235  hashtable->log2_nbuckets = my_log2(hashtable->nbuckets);
3236  hashtable->current_chunk = NULL;
3238  hashtable->batches[batchno].at_least_one_chunk = false;
3239 }
dsa_pointer current_chunk_shared
Definition: hashjoin.h:359
dsa_pointer_atomic * shared
Definition: hashjoin.h:299
#define InvalidDsaPointer
Definition: dsa.h:78
dsa_area * area
Definition: hashjoin.h:356
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:932
int my_log2(long num)
Definition: dynahash.c:1718
ParallelHashJoinState * parallel_state
Definition: hashjoin.h:357
ParallelHashJoinBatchAccessor * batches
Definition: hashjoin.h:358
#define Assert(condition)
Definition: c.h:739
union HashJoinTableData::@97 buckets
ParallelHashJoinBatch * shared
Definition: hashjoin.h:197
HashMemoryChunk current_chunk
Definition: hashjoin.h:355
dsa_pointer buckets
Definition: hashjoin.h:153

◆ ExecParallelScanHashBucket()

bool ExecParallelScanHashBucket ( HashJoinState hjstate,
ExprContext econtext 
)

Definition at line 1988 of file nodeHash.c.

References ExprContext::ecxt_innertuple, ExecParallelHashFirstTuple(), ExecParallelHashNextTuple(), ExecQualAndReset(), ExecStoreMinimalTuple(), HashJoinState::hashclauses, HashJoinTupleData::hashvalue, HashJoinState::hj_CurBucketNo, HashJoinState::hj_CurHashValue, HashJoinState::hj_CurTuple, HashJoinState::hj_HashTable, HashJoinState::hj_HashTupleSlot, and HJTUPLE_MINTUPLE.

Referenced by ExecHashJoinImpl().

1990 {
1991  ExprState *hjclauses = hjstate->hashclauses;
1992  HashJoinTable hashtable = hjstate->hj_HashTable;
1993  HashJoinTuple hashTuple = hjstate->hj_CurTuple;
1994  uint32 hashvalue = hjstate->hj_CurHashValue;
1995 
1996  /*
1997  * hj_CurTuple is the address of the tuple last returned from the current
1998  * bucket, or NULL if it's time to start scanning a new bucket.
1999  */
2000  if (hashTuple != NULL)
2001  hashTuple = ExecParallelHashNextTuple(hashtable, hashTuple);
2002  else
2003  hashTuple = ExecParallelHashFirstTuple(hashtable,
2004  hjstate->hj_CurBucketNo);
2005 
2006  while (hashTuple != NULL)
2007  {
2008  if (hashTuple->hashvalue == hashvalue)
2009  {
2010  TupleTableSlot *inntuple;
2011 
2012  /* insert hashtable's tuple into exec slot so ExecQual sees it */
2013  inntuple = ExecStoreMinimalTuple(HJTUPLE_MINTUPLE(hashTuple),
2014  hjstate->hj_HashTupleSlot,
2015  false); /* do not pfree */
2016  econtext->ecxt_innertuple = inntuple;
2017 
2018  if (ExecQualAndReset(hjclauses, econtext))
2019  {
2020  hjstate->hj_CurTuple = hashTuple;
2021  return true;
2022  }
2023  }
2024 
2025  hashTuple = ExecParallelHashNextTuple(hashtable, hashTuple);
2026  }
2027 
2028  /*
2029  * no match
2030  */
2031  return false;
2032 }
TupleTableSlot * ExecStoreMinimalTuple(MinimalTuple mtup, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:1416
uint32 hj_CurHashValue
Definition: execnodes.h:1934
HashJoinTuple hj_CurTuple
Definition: execnodes.h:1937
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:225
unsigned int uint32
Definition: c.h:359
int hj_CurBucketNo
Definition: execnodes.h:1935
static bool ExecQualAndReset(ExprState *state, ExprContext *econtext)
Definition: executor.h:392
#define HJTUPLE_MINTUPLE(hjtup)
Definition: hashjoin.h:80
static HashJoinTuple ExecParallelHashFirstTuple(HashJoinTable table, int bucketno)
Definition: nodeHash.c:3178
TupleTableSlot * hj_HashTupleSlot
Definition: execnodes.h:1939
static HashJoinTuple ExecParallelHashNextTuple(HashJoinTable table, HashJoinTuple tuple)
Definition: nodeHash.c:3194
HashJoinTable hj_HashTable
Definition: execnodes.h:1933
uint32 hashvalue
Definition: hashjoin.h:75
ExprState * hashclauses
Definition: execnodes.h:1929

◆ ExecPrepHashTableForUnmatched()

void ExecPrepHashTableForUnmatched ( HashJoinState hjstate)

Definition at line 2039 of file nodeHash.c.

References HashJoinState::hj_CurBucketNo, HashJoinState::hj_CurSkewBucketNo, and HashJoinState::hj_CurTuple.

Referenced by ExecHashJoinImpl().

2040 {
2041  /*----------
2042  * During this scan we use the HashJoinState fields as follows:
2043  *
2044  * hj_CurBucketNo: next regular bucket to scan
2045  * hj_CurSkewBucketNo: next skew bucket (an index into skewBucketNums)
2046  * hj_CurTuple: last tuple returned, or NULL to start next bucket
2047  *----------
2048  */
2049  hjstate->hj_CurBucketNo = 0;
2050  hjstate->hj_CurSkewBucketNo = 0;
2051  hjstate->hj_CurTuple = NULL;
2052 }
int hj_CurSkewBucketNo
Definition: execnodes.h:1936
HashJoinTuple hj_CurTuple
Definition: execnodes.h:1937
int hj_CurBucketNo
Definition: execnodes.h:1935

◆ ExecReScanHash()

void ExecReScanHash ( HashState node)

Definition at line 2189 of file nodeHash.c.

References PlanState::chgParam, ExecReScan(), PlanState::lefttree, and HashState::ps.

Referenced by ExecReScan().

2190 {
2191  /*
2192  * if chgParam of subnode is not null then plan will be re-scanned by
2193  * first ExecProcNode.
2194  */
2195  if (node->ps.lefttree->chgParam == NULL)
2196  ExecReScan(node->ps.lefttree);
2197 }
void ExecReScan(PlanState *node)
Definition: execAmi.c:75
struct PlanState * lefttree
Definition: execnodes.h:961
PlanState ps
Definition: execnodes.h:2266
Bitmapset * chgParam
Definition: execnodes.h:971

◆ ExecScanHashBucket()

bool ExecScanHashBucket ( HashJoinState hjstate,
ExprContext econtext 
)

Definition at line 1927 of file nodeHash.c.

References HashJoinTableData::buckets, ExprContext::ecxt_innertuple, ExecQualAndReset(), ExecStoreMinimalTuple(), HashJoinState::hashclauses, HashJoinTupleData::hashvalue, HashJoinState::hj_CurBucketNo, HashJoinState::hj_CurHashValue, HashJoinState::hj_CurSkewBucketNo, HashJoinState::hj_CurTuple, HashJoinState::hj_HashTable, HashJoinState::hj_HashTupleSlot, HJTUPLE_MINTUPLE, INVALID_SKEW_BUCKET_NO, HashJoinTupleData::next, HashJoinTableData::skewBucket, HashSkewBucket::tuples, HashJoinTupleData::unshared, and HashJoinTableData::unshared.

Referenced by ExecHashJoinImpl().

1929 {
1930  ExprState *hjclauses = hjstate->hashclauses;
1931  HashJoinTable hashtable = hjstate->hj_HashTable;
1932  HashJoinTuple hashTuple = hjstate->hj_CurTuple;
1933  uint32 hashvalue = hjstate->hj_CurHashValue;
1934 
1935  /*
1936  * hj_CurTuple is the address of the tuple last returned from the current
1937  * bucket, or NULL if it's time to start scanning a new bucket.
1938  *
1939  * If the tuple hashed to a skew bucket then scan the skew bucket
1940  * otherwise scan the standard hashtable bucket.
1941  */
1942  if (hashTuple != NULL)
1943  hashTuple = hashTuple->next.unshared;
1944  else if (hjstate->hj_CurSkewBucketNo != INVALID_SKEW_BUCKET_NO)
1945  hashTuple = hashtable->skewBucket[hjstate->hj_CurSkewBucketNo]->tuples;
1946  else
1947  hashTuple = hashtable->buckets.unshared[hjstate->hj_CurBucketNo];
1948 
1949  while (hashTuple != NULL)
1950  {
1951  if (hashTuple->hashvalue == hashvalue)
1952  {
1953  TupleTableSlot *inntuple;
1954 
1955  /* insert hashtable's tuple into exec slot so ExecQual sees it */
1956  inntuple = ExecStoreMinimalTuple(HJTUPLE_MINTUPLE(hashTuple),
1957  hjstate->hj_HashTupleSlot,
1958  false); /* do not pfree */
1959  econtext->ecxt_innertuple = inntuple;
1960 
1961  if (ExecQualAndReset(hjclauses, econtext))
1962  {
1963  hjstate->hj_CurTuple = hashTuple;
1964  return true;
1965  }
1966  }
1967 
1968  hashTuple = hashTuple->next.unshared;
1969  }
1970 
1971  /*
1972  * no match
1973  */
1974  return false;
1975 }
#define INVALID_SKEW_BUCKET_NO
Definition: hashjoin.h:109
TupleTableSlot * ExecStoreMinimalTuple(MinimalTuple mtup, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:1416
union HashJoinTupleData::@95 next
uint32 hj_CurHashValue
Definition: execnodes.h:1934
int hj_CurSkewBucketNo
Definition: execnodes.h:1936
struct HashJoinTupleData * unshared
Definition: hashjoin.h:72
HashJoinTuple hj_CurTuple
Definition: execnodes.h:1937
HashJoinTuple tuples
Definition: hashjoin.h:105
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:225
unsigned int uint32
Definition: c.h:359
int hj_CurBucketNo
Definition: execnodes.h:1935
static bool ExecQualAndReset(ExprState *state, ExprContext *econtext)
Definition: executor.h:392
HashSkewBucket ** skewBucket
Definition: hashjoin.h:305
#define HJTUPLE_MINTUPLE(hjtup)
Definition: hashjoin.h:80
union HashJoinTableData::@97 buckets
TupleTableSlot * hj_HashTupleSlot
Definition: execnodes.h:1939
HashJoinTable hj_HashTable
Definition: execnodes.h:1933
struct HashJoinTupleData ** unshared
Definition: hashjoin.h:297
uint32 hashvalue
Definition: hashjoin.h:75
ExprState * hashclauses
Definition: execnodes.h:1929

◆ ExecScanHashTableForUnmatched()

bool ExecScanHashTableForUnmatched ( HashJoinState hjstate,
ExprContext econtext 
)

Definition at line 2063 of file nodeHash.c.

References HashJoinTableData::buckets, CHECK_FOR_INTERRUPTS, ExprContext::ecxt_innertuple, ExecStoreMinimalTuple(), HeapTupleHeaderHasMatch, HashJoinState::hj_CurBucketNo, HashJoinState::hj_CurSkewBucketNo, HashJoinState::hj_CurTuple, HashJoinState::hj_HashTable, HashJoinState::hj_HashTupleSlot, HJTUPLE_MINTUPLE, HashJoinTableData::nbuckets, HashJoinTupleData::next, HashJoinTableData::nSkewBuckets, ResetExprContext, HashJoinTableData::skewBucket, HashJoinTableData::skewBucketNums, HashSkewBucket::tuples, HashJoinTupleData::unshared, and HashJoinTableData::unshared.

Referenced by ExecHashJoinImpl().

2064 {
2065  HashJoinTable hashtable = hjstate->hj_HashTable;
2066  HashJoinTuple hashTuple = hjstate->hj_CurTuple;
2067 
2068  for (;;)
2069  {
2070  /*
2071  * hj_CurTuple is the address of the tuple last returned from the
2072  * current bucket, or NULL if it's time to start scanning a new
2073  * bucket.
2074  */
2075  if (hashTuple != NULL)
2076  hashTuple = hashTuple->next.unshared;
2077  else if (hjstate->hj_CurBucketNo < hashtable->nbuckets)
2078  {
2079  hashTuple = hashtable->buckets.unshared[hjstate->hj_CurBucketNo];
2080  hjstate->hj_CurBucketNo++;
2081  }
2082  else if (hjstate->hj_CurSkewBucketNo < hashtable->nSkewBuckets)
2083  {
2084  int j = hashtable->skewBucketNums[hjstate->hj_CurSkewBucketNo];
2085 
2086  hashTuple = hashtable->skewBucket[j]->tuples;
2087  hjstate->hj_CurSkewBucketNo++;
2088  }
2089  else
2090  break; /* finished all buckets */
2091 
2092  while (hashTuple != NULL)
2093  {
2094  if (!HeapTupleHeaderHasMatch(HJTUPLE_MINTUPLE(hashTuple)))
2095  {
2096  TupleTableSlot *inntuple;
2097 
2098  /* insert hashtable's tuple into exec slot */
2099  inntuple = ExecStoreMinimalTuple(HJTUPLE_MINTUPLE(hashTuple),
2100  hjstate->hj_HashTupleSlot,
2101  false); /* do not pfree */
2102  econtext->ecxt_innertuple = inntuple;
2103 
2104  /*
2105  * Reset temp memory each time; although this function doesn't
2106  * do any qual eval, the caller will, so let's keep it
2107  * parallel to ExecScanHashBucket.
2108  */
2109  ResetExprContext(econtext);
2110 
2111  hjstate->hj_CurTuple = hashTuple;
2112  return true;
2113  }
2114 
2115  hashTuple = hashTuple->next.unshared;
2116  }
2117 
2118  /* allow this loop to be cancellable */
2120  }
2121 
2122  /*
2123  * no more unmatched tuples
2124  */
2125  return false;
2126 }
TupleTableSlot * ExecStoreMinimalTuple(MinimalTuple mtup, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:1416
union HashJoinTupleData::@95 next
int * skewBucketNums
Definition: hashjoin.h:308
int hj_CurSkewBucketNo
Definition: execnodes.h:1936
struct HashJoinTupleData * unshared
Definition: hashjoin.h:72
HashJoinTuple hj_CurTuple
Definition: execnodes.h:1937
HashJoinTuple tuples
Definition: hashjoin.h:105
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:225
int hj_CurBucketNo
Definition: execnodes.h:1935
HashSkewBucket ** skewBucket
Definition: hashjoin.h:305
#define HJTUPLE_MINTUPLE(hjtup)
Definition: hashjoin.h:80
#define HeapTupleHeaderHasMatch(tup)
Definition: htup_details.h:516
union HashJoinTableData::@97 buckets
TupleTableSlot * hj_HashTupleSlot
Definition: execnodes.h:1939
HashJoinTable hj_HashTable
Definition: execnodes.h:1933
struct HashJoinTupleData ** unshared
Definition: hashjoin.h:297
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
#define ResetExprContext(econtext)
Definition: executor.h:495

◆ ExecShutdownHash()

void ExecShutdownHash ( HashState node)

Definition at line 2630 of file nodeHash.c.

References ExecHashGetInstrumentation(), HashState::hashtable, and HashState::hinstrument.

Referenced by ExecShutdownNode().

2631 {
2632  if (node->hinstrument && node->hashtable)
2634 }
void ExecHashGetInstrumentation(HashInstrumentation *instrument, HashJoinTable hashtable)
Definition: nodeHash.c:2661
HashJoinTable hashtable
Definition: execnodes.h:2267
HashInstrumentation * hinstrument
Definition: execnodes.h:2271

◆ MultiExecHash()

Node* MultiExecHash ( HashState node)

Definition at line 104 of file nodeHash.c.

References HashState::hashtable, InstrStartNode(), InstrStopNode(), PlanState::instrument, MultiExecParallelHash(), MultiExecPrivateHash(), HashState::parallel_state, HashJoinTableData::partialTuples, and HashState::ps.

Referenced by MultiExecProcNode().

105 {
106  /* must provide our own instrumentation support */
107  if (node->ps.instrument)
109 
110  if (node->parallel_state != NULL)
111  MultiExecParallelHash(node);
112  else
113  MultiExecPrivateHash(node);
114 
115  /* must provide our own instrumentation support */
116  if (node->ps.instrument)
118 
119  /*
120  * We do not return the hash table directly because it's not a subtype of
121  * Node, and so would violate the MultiExecProcNode API. Instead, our
122  * parent Hashjoin node is expected to know how to fish it out of our node
123  * state. Ugly but not really worth cleaning up, since Hashjoin knows
124  * quite a bit more about Hash besides that.
125  */
126  return NULL;
127 }
struct ParallelHashJoinState * parallel_state
Definition: execnodes.h:2274
void InstrStopNode(Instrumentation *instr, double nTuples)
Definition: instrument.c:76
Instrumentation * instrument
Definition: execnodes.h:949
HashJoinTable hashtable
Definition: execnodes.h:2267
static void MultiExecPrivateHash(HashState *node)
Definition: nodeHash.c:137
double partialTuples
Definition: hashjoin.h:319
void InstrStartNode(Instrumentation *instr)
Definition: instrument.c:63
PlanState ps
Definition: execnodes.h:2266
static void MultiExecParallelHash(HashState *node)
Definition: nodeHash.c:213