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 667 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().

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

◆ ExecEndHash()

void ExecEndHash ( HashState node)

Definition at line 406 of file nodeHash.c.

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

Referenced by ExecEndNode().

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

◆ ExecHashEstimate()

void ExecHashEstimate ( HashState node,
ParallelContext pcxt 
)

Definition at line 2570 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().

2571 {
2572  size_t size;
2573 
2574  /* don't need this if not instrumenting or no workers */
2575  if (!node->ps.instrument || pcxt->nworkers == 0)
2576  return;
2577 
2578  size = mul_size(pcxt->nworkers, sizeof(HashInstrumentation));
2579  size = add_size(size, offsetof(SharedHashInfo, hinstrument));
2580  shm_toc_estimate_chunk(&pcxt->estimator, size);
2581  shm_toc_estimate_keys(&pcxt->estimator, 1);
2582 }
Instrumentation * instrument
Definition: execnodes.h:950
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:2271
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:655

◆ ExecHashGetBucketAndBatch()

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

Definition at line 1896 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().

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

◆ ExecHashGetHashValue()

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

Definition at line 1792 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().

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

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

Referenced by ExecHashJoinImpl(), and MultiExecPrivateHash().

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

2590 {
2591  size_t size;
2592 
2593  /* don't need this if not instrumenting or no workers */
2594  if (!node->ps.instrument || pcxt->nworkers == 0)
2595  return;
2596 
2597  size = offsetof(SharedHashInfo, hinstrument) +
2598  pcxt->nworkers * sizeof(HashInstrumentation);
2599  node->shared_info = (SharedHashInfo *) shm_toc_allocate(pcxt->toc, size);
2600  memset(node->shared_info, 0, size);
2601  node->shared_info->num_workers = pcxt->nworkers;
2602  shm_toc_insert(pcxt->toc, node->ps.plan->plan_node_id,
2603  node->shared_info);
2604 }
Instrumentation * instrument
Definition: execnodes.h:950
struct HashInstrumentation HashInstrumentation
int plan_node_id
Definition: plannodes.h:139
SharedHashInfo * shared_info
Definition: execnodes.h:2275
PlanState ps
Definition: execnodes.h:2271
Plan * plan
Definition: execnodes.h:940
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:655
shm_toc * toc
Definition: parallel.h:44

◆ ExecHashInitializeWorker()

void ExecHashInitializeWorker ( HashState node,
ParallelWorkerContext pwcxt 
)

Definition at line 2611 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().

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

◆ ExecHashRetrieveInstrumentation()

void ExecHashRetrieveInstrumentation ( HashState node)

Definition at line 2642 of file nodeHash.c.

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

Referenced by ExecParallelRetrieveInstrumentation().

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

◆ ExecHashTableCreate()

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

Definition at line 430 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().

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

◆ ExecHashTableDestroy()

void ExecHashTableDestroy ( HashJoinTable  hashtable)

Definition at line 854 of file nodeHash.c.

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

Referenced by ExecEndHashJoin(), and ExecReScanHashJoin().

855 {
856  int i;
857 
858  /*
859  * Make sure all the temp files are closed. We skip batch 0, since it
860  * can't have any temp files (and the arrays might not even exist if
861  * nbatch is only 1). Parallel hash joins don't use these files.
862  */
863  if (hashtable->innerBatchFile != NULL)
864  {
865  for (i = 1; i < hashtable->nbatch; i++)
866  {
867  if (hashtable->innerBatchFile[i])
868  BufFileClose(hashtable->innerBatchFile[i]);
869  if (hashtable->outerBatchFile[i])
870  BufFileClose(hashtable->outerBatchFile[i]);
871  }
872  }
873 
874  /* Release working memory (batchCxt is a child, so it goes away too) */
875  MemoryContextDelete(hashtable->hashCxt);
876 
877  /* And drop the control block */
878  pfree(hashtable);
879 }
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 3142 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().

3143 {
3144  if (hashtable->parallel_state)
3145  {
3146  ParallelHashJoinState *pstate = hashtable->parallel_state;
3147  int i;
3148 
3149  /* Make sure any temporary files are closed. */
3150  if (hashtable->batches)
3151  {
3152  for (i = 0; i < hashtable->nbatch; ++i)
3153  {
3154  sts_end_write(hashtable->batches[i].inner_tuples);
3155  sts_end_write(hashtable->batches[i].outer_tuples);
3158  }
3159  }
3160 
3161  /* If we're last to detach, clean up shared memory. */
3162  if (BarrierDetach(&pstate->build_barrier))
3163  {
3164  if (DsaPointerIsValid(pstate->batches))
3165  {
3166  dsa_free(hashtable->area, pstate->batches);
3167  pstate->batches = InvalidDsaPointer;
3168  }
3169  }
3170 
3171  hashtable->parallel_state = NULL;
3172  }
3173 }
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 3085 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().

3086 {
3087  if (hashtable->parallel_state != NULL &&
3088  hashtable->curbatch >= 0)
3089  {
3090  int curbatch = hashtable->curbatch;
3091  ParallelHashJoinBatch *batch = hashtable->batches[curbatch].shared;
3092 
3093  /* Make sure any temporary files are closed. */
3094  sts_end_parallel_scan(hashtable->batches[curbatch].inner_tuples);
3095  sts_end_parallel_scan(hashtable->batches[curbatch].outer_tuples);
3096 
3097  /* Detach from the batch we were last working on. */
3099  {
3100  /*
3101  * Technically we shouldn't access the barrier because we're no
3102  * longer attached, but since there is no way it's moving after
3103  * this point it seems safe to make the following assertion.
3104  */
3106 
3107  /* Free shared chunks and buckets. */
3108  while (DsaPointerIsValid(batch->chunks))
3109  {
3110  HashMemoryChunk chunk =
3111  dsa_get_address(hashtable->area, batch->chunks);
3112  dsa_pointer next = chunk->next.shared;
3113 
3114  dsa_free(hashtable->area, batch->chunks);
3115  batch->chunks = next;
3116  }
3117  if (DsaPointerIsValid(batch->buckets))
3118  {
3119  dsa_free(hashtable->area, batch->buckets);
3120  batch->buckets = InvalidDsaPointer;
3121  }
3122  }
3123 
3124  /*
3125  * Track the largest batch we've been attached to. Though each
3126  * backend might see a different subset of batches, explain.c will
3127  * scan the results from all backends to find the largest value.
3128  */
3129  hashtable->spacePeak =
3130  Max(hashtable->spacePeak,
3131  batch->size + sizeof(dsa_pointer_atomic) * hashtable->nbuckets);
3132 
3133  /* Remember that we are not attached to a batch. */
3134  hashtable->curbatch = -1;
3135  }
3136 }
SharedTuplestoreAccessor * outer_tuples
Definition: hashjoin.h:209
#define PHJ_BATCH_DONE
Definition: hashjoin.h:268
static int32 next
Definition: blutils.c:215
#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:898
#define Assert(condition)
Definition: c.h:732
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 1594 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().

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

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

Referenced by ExecHashJoinNewBatch().

2136 {
2137  MemoryContext oldcxt;
2138  int nbuckets = hashtable->nbuckets;
2139 
2140  /*
2141  * Release all the hash buckets and tuples acquired in the prior pass, and
2142  * reinitialize the context for a new pass.
2143  */
2144  MemoryContextReset(hashtable->batchCxt);
2145  oldcxt = MemoryContextSwitchTo(hashtable->batchCxt);
2146 
2147  /* Reallocate and reinitialize the hash bucket headers. */
2148  hashtable->buckets.unshared = (HashJoinTuple *)
2149  palloc0(nbuckets * sizeof(HashJoinTuple));
2150 
2151  hashtable->spaceUsed = 0;
2152 
2153  MemoryContextSwitchTo(oldcxt);
2154 
2155  /* Forget the chunks (the memory was freed by the context reset above). */
2156  hashtable->chunks = NULL;
2157 }
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 2164 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().

2165 {
2166  HashJoinTuple tuple;
2167  int i;
2168 
2169  /* Reset all flags in the main table ... */
2170  for (i = 0; i < hashtable->nbuckets; i++)
2171  {
2172  for (tuple = hashtable->buckets.unshared[i]; tuple != NULL;
2173  tuple = tuple->next.unshared)
2175  }
2176 
2177  /* ... and the same for the skew buckets, if any */
2178  for (i = 0; i < hashtable->nSkewBuckets; i++)
2179  {
2180  int j = hashtable->skewBucketNums[i];
2181  HashSkewBucket *skewBucket = hashtable->skewBucket[j];
2182 
2183  for (tuple = skewBucket->tuples; tuple != NULL; tuple = tuple->next.unshared)
2185  }
2186 }
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 353 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().

354 {
355  HashState *hashstate;
356 
357  /* check for unsupported flags */
358  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
359 
360  /*
361  * create state structure
362  */
363  hashstate = makeNode(HashState);
364  hashstate->ps.plan = (Plan *) node;
365  hashstate->ps.state = estate;
366  hashstate->ps.ExecProcNode = ExecHash;
367  hashstate->hashtable = NULL;
368  hashstate->hashkeys = NIL; /* will be set by parent HashJoin */
369 
370  /*
371  * Miscellaneous initialization
372  *
373  * create expression context for node
374  */
375  ExecAssignExprContext(estate, &hashstate->ps);
376 
377  /*
378  * initialize child nodes
379  */
380  outerPlanState(hashstate) = ExecInitNode(outerPlan(node), estate, eflags);
381 
382  /*
383  * initialize our result slot and type. No need to build projection
384  * because this node doesn't do projections.
385  */
387  hashstate->ps.ps_ProjInfo = NULL;
388 
389  /*
390  * initialize child expressions
391  */
392  Assert(node->plan.qual == NIL);
393  hashstate->hashkeys =
394  ExecInitExprList(node->hashkeys, (PlanState *) hashstate);
395 
396  return hashstate;
397 }
#define NIL
Definition: pg_list.h:65
List * qual
Definition: plannodes.h:141
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:980
HashJoinTable hashtable
Definition: execnodes.h:2272
EState * state
Definition: execnodes.h:942
#define EXEC_FLAG_BACKWARD
Definition: executor.h:58
#define outerPlanState(node)
Definition: execnodes.h:1034
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:316
List * hashkeys
Definition: execnodes.h:2273
PlanState ps
Definition: execnodes.h:2271
#define outerPlan(node)
Definition: plannodes.h:170
static TupleTableSlot * ExecHash(PlanState *pstate)
Definition: nodeHash.c:91
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:946
List * hashkeys
Definition: plannodes.h:915
Plan * plan
Definition: execnodes.h:940
#define makeNode(_type_)
Definition: nodes.h:573
#define Assert(condition)
Definition: c.h:732
#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:1764
Plan plan
Definition: plannodes.h:909
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:139
const TupleTableSlotOps TTSOpsMinimalTuple
Definition: execTuples.c:86

◆ ExecParallelHashTableAlloc()

void ExecParallelHashTableAlloc ( HashJoinTable  hashtable,
int  batchno 
)

Definition at line 3065 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().

3066 {
3067  ParallelHashJoinBatch *batch = hashtable->batches[batchno].shared;
3068  dsa_pointer_atomic *buckets;
3069  int nbuckets = hashtable->parallel_state->nbuckets;
3070  int i;
3071 
3072  batch->buckets =
3073  dsa_allocate(hashtable->area, sizeof(dsa_pointer_atomic) * nbuckets);
3074  buckets = (dsa_pointer_atomic *)
3075  dsa_get_address(hashtable->area, batch->buckets);
3076  for (i = 0; i < nbuckets; ++i)
3078 }
#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 1683 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().

1686 {
1687  bool shouldFree;
1688  MinimalTuple tuple = ExecFetchSlotMinimalTuple(slot, &shouldFree);
1689  dsa_pointer shared;
1690  int bucketno;
1691  int batchno;
1692 
1693 retry:
1694  ExecHashGetBucketAndBatch(hashtable, hashvalue, &bucketno, &batchno);
1695 
1696  if (batchno == 0)
1697  {
1698  HashJoinTuple hashTuple;
1699 
1700  /* Try to load it into memory. */
1703  hashTuple = ExecParallelHashTupleAlloc(hashtable,
1704  HJTUPLE_OVERHEAD + tuple->t_len,
1705  &shared);
1706  if (hashTuple == NULL)
1707  goto retry;
1708 
1709  /* Store the hash value in the HashJoinTuple header. */
1710  hashTuple->hashvalue = hashvalue;
1711  memcpy(HJTUPLE_MINTUPLE(hashTuple), tuple, tuple->t_len);
1712 
1713  /* Push it onto the front of the bucket's list */
1714  ExecParallelHashPushTuple(&hashtable->buckets.shared[bucketno],
1715  hashTuple, shared);
1716  }
1717  else
1718  {
1719  size_t tuple_size = MAXALIGN(HJTUPLE_OVERHEAD + tuple->t_len);
1720 
1721  Assert(batchno > 0);
1722 
1723  /* Try to preallocate space in the batch if necessary. */
1724  if (hashtable->batches[batchno].preallocated < tuple_size)
1725  {
1726  if (!ExecParallelHashTuplePrealloc(hashtable, batchno, tuple_size))
1727  goto retry;
1728  }
1729 
1730  Assert(hashtable->batches[batchno].preallocated >= tuple_size);
1731  hashtable->batches[batchno].preallocated -= tuple_size;
1732  sts_puttuple(hashtable->batches[batchno].inner_tuples, &hashvalue,
1733  tuple);
1734  }
1735  ++hashtable->batches[batchno].ntuples;
1736 
1737  if (shouldFree)
1738  heap_free_minimal_tuple(tuple);
1739 }
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:1657
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:1896
void heap_free_minimal_tuple(MinimalTuple mtup)
Definition: heaptuple.c:1427
static bool ExecParallelHashTuplePrealloc(HashJoinTable hashtable, int batchno, size_t size)
Definition: nodeHash.c:3289
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:732
int BarrierPhase(Barrier *barrier)
Definition: barrier.c:243
#define MAXALIGN(LEN)
Definition: c.h:685
union HashJoinTableData::@97 buckets
static void ExecParallelHashPushTuple(dsa_pointer_atomic *head, HashJoinTuple tuple, dsa_pointer tuple_shared)
Definition: nodeHash.c:3209
#define PHJ_BUILD_HASHING_INNER
Definition: hashjoin.h:259
static HashJoinTuple ExecParallelHashTupleAlloc(HashJoinTable hashtable, size_t size, dsa_pointer *shared)
Definition: nodeHash.c:2756
uint32 hashvalue
Definition: hashjoin.h:75

◆ ExecParallelHashTableInsertCurrentBatch()

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

Definition at line 1748 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().

1751 {
1752  bool shouldFree;
1753  MinimalTuple tuple = ExecFetchSlotMinimalTuple(slot, &shouldFree);
1754  HashJoinTuple hashTuple;
1755  dsa_pointer shared;
1756  int batchno;
1757  int bucketno;
1758 
1759  ExecHashGetBucketAndBatch(hashtable, hashvalue, &bucketno, &batchno);
1760  Assert(batchno == hashtable->curbatch);
1761  hashTuple = ExecParallelHashTupleAlloc(hashtable,
1762  HJTUPLE_OVERHEAD + tuple->t_len,
1763  &shared);
1764  hashTuple->hashvalue = hashvalue;
1765  memcpy(HJTUPLE_MINTUPLE(hashTuple), tuple, tuple->t_len);
1767  ExecParallelHashPushTuple(&hashtable->buckets.shared[bucketno],
1768  hashTuple, shared);
1769 
1770  if (shouldFree)
1771  heap_free_minimal_tuple(tuple);
1772 }
dsa_pointer_atomic * shared
Definition: hashjoin.h:299
MinimalTuple ExecFetchSlotMinimalTuple(TupleTableSlot *slot, bool *shouldFree)
Definition: execTuples.c:1657
uint64 dsa_pointer
Definition: dsa.h:62
void ExecHashGetBucketAndBatch(HashJoinTable hashtable, uint32 hashvalue, int *bucketno, int *batchno)
Definition: nodeHash.c:1896
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:732
#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:3209
static HashJoinTuple ExecParallelHashTupleAlloc(HashJoinTable hashtable, size_t size, dsa_pointer *shared)
Definition: nodeHash.c:2756
uint32 hashvalue
Definition: hashjoin.h:75

◆ ExecParallelHashTableSetCurrentBatch()

void ExecParallelHashTableSetCurrentBatch ( HashJoinTable  hashtable,
int  batchno 
)

Definition at line 3227 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().

3228 {
3229  Assert(hashtable->batches[batchno].shared->buckets != InvalidDsaPointer);
3230 
3231  hashtable->curbatch = batchno;
3232  hashtable->buckets.shared = (dsa_pointer_atomic *)
3233  dsa_get_address(hashtable->area,
3234  hashtable->batches[batchno].shared->buckets);
3235  hashtable->nbuckets = hashtable->parallel_state->nbuckets;
3236  hashtable->log2_nbuckets = my_log2(hashtable->nbuckets);
3237  hashtable->current_chunk = NULL;
3239  hashtable->batches[batchno].at_least_one_chunk = false;
3240 }
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:732
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 1989 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().

1991 {
1992  ExprState *hjclauses = hjstate->hashclauses;
1993  HashJoinTable hashtable = hjstate->hj_HashTable;
1994  HashJoinTuple hashTuple = hjstate->hj_CurTuple;
1995  uint32 hashvalue = hjstate->hj_CurHashValue;
1996 
1997  /*
1998  * hj_CurTuple is the address of the tuple last returned from the current
1999  * bucket, or NULL if it's time to start scanning a new bucket.
2000  */
2001  if (hashTuple != NULL)
2002  hashTuple = ExecParallelHashNextTuple(hashtable, hashTuple);
2003  else
2004  hashTuple = ExecParallelHashFirstTuple(hashtable,
2005  hjstate->hj_CurBucketNo);
2006 
2007  while (hashTuple != NULL)
2008  {
2009  if (hashTuple->hashvalue == hashvalue)
2010  {
2011  TupleTableSlot *inntuple;
2012 
2013  /* insert hashtable's tuple into exec slot so ExecQual sees it */
2014  inntuple = ExecStoreMinimalTuple(HJTUPLE_MINTUPLE(hashTuple),
2015  hjstate->hj_HashTupleSlot,
2016  false); /* do not pfree */
2017  econtext->ecxt_innertuple = inntuple;
2018 
2019  if (ExecQualAndReset(hjclauses, econtext))
2020  {
2021  hjstate->hj_CurTuple = hashTuple;
2022  return true;
2023  }
2024  }
2025 
2026  hashTuple = ExecParallelHashNextTuple(hashtable, hashTuple);
2027  }
2028 
2029  /*
2030  * no match
2031  */
2032  return false;
2033 }
TupleTableSlot * ExecStoreMinimalTuple(MinimalTuple mtup, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:1411
uint32 hj_CurHashValue
Definition: execnodes.h:1939
HashJoinTuple hj_CurTuple
Definition: execnodes.h:1942
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:226
unsigned int uint32
Definition: c.h:358
int hj_CurBucketNo
Definition: execnodes.h:1940
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:3179
TupleTableSlot * hj_HashTupleSlot
Definition: execnodes.h:1944
static HashJoinTuple ExecParallelHashNextTuple(HashJoinTable table, HashJoinTuple tuple)
Definition: nodeHash.c:3195
HashJoinTable hj_HashTable
Definition: execnodes.h:1938
uint32 hashvalue
Definition: hashjoin.h:75
ExprState * hashclauses
Definition: execnodes.h:1934

◆ ExecPrepHashTableForUnmatched()

void ExecPrepHashTableForUnmatched ( HashJoinState hjstate)

Definition at line 2040 of file nodeHash.c.

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

Referenced by ExecHashJoinImpl().

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

◆ ExecReScanHash()

void ExecReScanHash ( HashState node)

Definition at line 2190 of file nodeHash.c.

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

Referenced by ExecReScan().

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

◆ ExecScanHashBucket()

bool ExecScanHashBucket ( HashJoinState hjstate,
ExprContext econtext 
)

Definition at line 1928 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().

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

◆ ExecScanHashTableForUnmatched()

bool ExecScanHashTableForUnmatched ( HashJoinState hjstate,
ExprContext econtext 
)

Definition at line 2064 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().

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

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

Referenced by ExecShutdownNode().

2632 {
2633  if (node->hinstrument && node->hashtable)
2635 }
void ExecHashGetInstrumentation(HashInstrumentation *instrument, HashJoinTable hashtable)
Definition: nodeHash.c:2662
HashJoinTable hashtable
Definition: execnodes.h:2272
HashInstrumentation * hinstrument
Definition: execnodes.h:2276

◆ MultiExecHash()

Node* MultiExecHash ( HashState node)

Definition at line 105 of file nodeHash.c.

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

Referenced by MultiExecProcNode().

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