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, 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 661 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().

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

◆ ExecEndHash()

void ExecEndHash ( HashState node)

Definition at line 404 of file nodeHash.c.

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

Referenced by ExecEndNode().

405 {
407 
408  /*
409  * free exprcontext
410  */
411  ExecFreeExprContext(&node->ps);
412 
413  /*
414  * shut down the subplan
415  */
416  outerPlan = outerPlanState(node);
417  ExecEndNode(outerPlan);
418 }
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:539
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:561
#define outerPlanState(node)
Definition: execnodes.h:914
PlanState ps
Definition: execnodes.h:2058
#define outerPlan(node)
Definition: plannodes.h:174

◆ ExecHashEstimate()

void ExecHashEstimate ( HashState node,
ParallelContext pcxt 
)

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

2544 {
2545  size_t size;
2546 
2547  /* don't need this if not instrumenting or no workers */
2548  if (!node->ps.instrument || pcxt->nworkers == 0)
2549  return;
2550 
2551  size = mul_size(pcxt->nworkers, sizeof(HashInstrumentation));
2552  size = add_size(size, offsetof(SharedHashInfo, hinstrument));
2553  shm_toc_estimate_chunk(&pcxt->estimator, size);
2554  shm_toc_estimate_keys(&pcxt->estimator, 1);
2555 }
Instrumentation * instrument
Definition: execnodes.h:878
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:2058
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:611

◆ ExecHashGetBucketAndBatch()

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

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

1878 {
1879  uint32 nbuckets = (uint32) hashtable->nbuckets;
1880  uint32 nbatch = (uint32) hashtable->nbatch;
1881 
1882  if (nbatch > 1)
1883  {
1884  /* we can do MOD by masking, DIV by shifting */
1885  *bucketno = hashvalue & (nbuckets - 1);
1886  *batchno = (hashvalue >> hashtable->log2_nbuckets) & (nbatch - 1);
1887  }
1888  else
1889  {
1890  *bucketno = hashvalue & (nbuckets - 1);
1891  *batchno = 0;
1892  }
1893 }
unsigned int uint32
Definition: c.h:314

◆ ExecHashGetHashValue()

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

Definition at line 1770 of file nodeHash.c.

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

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

1776 {
1777  uint32 hashkey = 0;
1778  FmgrInfo *hashfunctions;
1779  ListCell *hk;
1780  int i = 0;
1781  MemoryContext oldContext;
1782 
1783  /*
1784  * We reset the eval context each time to reclaim any memory leaked in the
1785  * hashkey expressions.
1786  */
1787  ResetExprContext(econtext);
1788 
1789  oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
1790 
1791  if (outer_tuple)
1792  hashfunctions = hashtable->outer_hashfunctions;
1793  else
1794  hashfunctions = hashtable->inner_hashfunctions;
1795 
1796  foreach(hk, hashkeys)
1797  {
1798  ExprState *keyexpr = (ExprState *) lfirst(hk);
1799  Datum keyval;
1800  bool isNull;
1801 
1802  /* rotate hashkey left 1 bit at each step */
1803  hashkey = (hashkey << 1) | ((hashkey & 0x80000000) ? 1 : 0);
1804 
1805  /*
1806  * Get the join attribute value of the tuple
1807  */
1808  keyval = ExecEvalExpr(keyexpr, econtext, &isNull);
1809 
1810  /*
1811  * If the attribute is NULL, and the join operator is strict, then
1812  * this tuple cannot pass the join qual so we can reject it
1813  * immediately (unless we're scanning the outside of an outer join, in
1814  * which case we must not reject it). Otherwise we act like the
1815  * hashcode of NULL is zero (this will support operators that act like
1816  * IS NOT DISTINCT, though not any more-random behavior). We treat
1817  * the hash support function as strict even if the operator is not.
1818  *
1819  * Note: currently, all hashjoinable operators must be strict since
1820  * the hash index AM assumes that. However, it takes so little extra
1821  * code here to allow non-strict that we may as well do it.
1822  */
1823  if (isNull)
1824  {
1825  if (hashtable->hashStrict[i] && !keep_nulls)
1826  {
1827  MemoryContextSwitchTo(oldContext);
1828  return false; /* cannot match */
1829  }
1830  /* else, leave hashkey unmodified, equivalent to hashcode 0 */
1831  }
1832  else
1833  {
1834  /* Compute the hash function */
1835  uint32 hkey;
1836 
1837  hkey = DatumGetUInt32(FunctionCall1(&hashfunctions[i], keyval));
1838  hashkey ^= hkey;
1839  }
1840 
1841  i++;
1842  }
1843 
1844  MemoryContextSwitchTo(oldContext);
1845 
1846  *hashvalue = hashkey;
1847  return true;
1848 }
#define DatumGetUInt32(X)
Definition: postgres.h:469
Definition: fmgr.h:56
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:217
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:282
unsigned int uint32
Definition: c.h:314
FmgrInfo * outer_hashfunctions
Definition: hashjoin.h:337
uintptr_t Datum
Definition: postgres.h:365
#define lfirst(lc)
Definition: pg_list.h:106
int i
#define FunctionCall1(flinfo, arg1)
Definition: fmgr.h:603
bool * hashStrict
Definition: hashjoin.h:339
#define ResetExprContext(econtext)
Definition: executor.h:484

◆ ExecHashGetInstrumentation()

void ExecHashGetInstrumentation ( HashInstrumentation instrument,
HashJoinTable  hashtable 
)

◆ ExecHashGetSkewBucket()

int ExecHashGetSkewBucket ( HashJoinTable  hashtable,
uint32  hashvalue 
)

Definition at line 2342 of file nodeHash.c.

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

Referenced by ExecHashJoinImpl(), and MultiExecPrivateHash().

2343 {
2344  int bucket;
2345 
2346  /*
2347  * Always return INVALID_SKEW_BUCKET_NO if not doing skew optimization (in
2348  * particular, this happens after the initial batch is done).
2349  */
2350  if (!hashtable->skewEnabled)
2351  return INVALID_SKEW_BUCKET_NO;
2352 
2353  /*
2354  * Since skewBucketLen is a power of 2, we can do a modulo by ANDing.
2355  */
2356  bucket = hashvalue & (hashtable->skewBucketLen - 1);
2357 
2358  /*
2359  * While we have not hit a hole in the hashtable and have not hit the
2360  * desired bucket, we have collided with some other hash value, so try the
2361  * next bucket location.
2362  */
2363  while (hashtable->skewBucket[bucket] != NULL &&
2364  hashtable->skewBucket[bucket]->hashvalue != hashvalue)
2365  bucket = (bucket + 1) & (hashtable->skewBucketLen - 1);
2366 
2367  /*
2368  * Found the desired bucket?
2369  */
2370  if (hashtable->skewBucket[bucket] != NULL)
2371  return bucket;
2372 
2373  /*
2374  * There must not be any hashtable entry for this hash value.
2375  */
2376  return INVALID_SKEW_BUCKET_NO;
2377 }
#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 2562 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().

2563 {
2564  size_t size;
2565 
2566  /* don't need this if not instrumenting or no workers */
2567  if (!node->ps.instrument || pcxt->nworkers == 0)
2568  return;
2569 
2570  size = offsetof(SharedHashInfo, hinstrument) +
2571  pcxt->nworkers * sizeof(HashInstrumentation);
2572  node->shared_info = (SharedHashInfo *) shm_toc_allocate(pcxt->toc, size);
2573  memset(node->shared_info, 0, size);
2574  node->shared_info->num_workers = pcxt->nworkers;
2575  shm_toc_insert(pcxt->toc, node->ps.plan->plan_node_id,
2576  node->shared_info);
2577 }
Instrumentation * instrument
Definition: execnodes.h:878
struct HashInstrumentation HashInstrumentation
int plan_node_id
Definition: plannodes.h:143
SharedHashInfo * shared_info
Definition: execnodes.h:2063
PlanState ps
Definition: execnodes.h:2058
Plan * plan
Definition: execnodes.h:868
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:611
shm_toc * toc
Definition: parallel.h:44

◆ ExecHashInitializeWorker()

void ExecHashInitializeWorker ( HashState node,
ParallelWorkerContext pwcxt 
)

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

2585 {
2586  SharedHashInfo *shared_info;
2587 
2588  /* don't need this if not instrumenting */
2589  if (!node->ps.instrument)
2590  return;
2591 
2592  shared_info = (SharedHashInfo *)
2593  shm_toc_lookup(pwcxt->toc, node->ps.plan->plan_node_id, false);
2594  node->hinstrument = &shared_info->hinstrument[ParallelWorkerNumber];
2595 }
Instrumentation * instrument
Definition: execnodes.h:878
int plan_node_id
Definition: plannodes.h:143
int ParallelWorkerNumber
Definition: parallel.c:103
PlanState ps
Definition: execnodes.h:2058
HashInstrumentation * hinstrument
Definition: execnodes.h:2064
HashInstrumentation hinstrument[FLEXIBLE_ARRAY_MEMBER]
Definition: execnodes.h:2049
Plan * plan
Definition: execnodes.h:868
void * shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
Definition: shm_toc.c:232

◆ ExecHashRetrieveInstrumentation()

void ExecHashRetrieveInstrumentation ( HashState node)

Definition at line 2615 of file nodeHash.c.

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

Referenced by ExecParallelRetrieveInstrumentation().

2616 {
2617  SharedHashInfo *shared_info = node->shared_info;
2618  size_t size;
2619 
2620  if (shared_info == NULL)
2621  return;
2622 
2623  /* Replace node->shared_info with a copy in backend-local memory. */
2624  size = offsetof(SharedHashInfo, hinstrument) +
2625  shared_info->num_workers * sizeof(HashInstrumentation);
2626  node->shared_info = palloc(size);
2627  memcpy(node->shared_info, shared_info, size);
2628 }
struct HashInstrumentation HashInstrumentation
SharedHashInfo * shared_info
Definition: execnodes.h:2063
void * palloc(Size size)
Definition: mcxt.c:835
#define offsetof(type, field)
Definition: c.h:611

◆ ExecHashTableCreate()

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

Definition at line 428 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::curbatch, HashJoinTableData::current_chunk, CurrentMemoryContext, elog, ERROR, EState::es_query_dsa, ExecChooseHashTableSize(), ExecHashBuildSkewHash(), ExecParallelHashJoinSetUpBatches(), ExecParallelHashTableAlloc(), fmgr_info(), 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, PlanState::plan, Hash::plan, Plan::plan_rows, Plan::plan_width, PrepareTempTablespaces(), 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().

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

◆ ExecHashTableDestroy()

void ExecHashTableDestroy ( HashJoinTable  hashtable)

Definition at line 848 of file nodeHash.c.

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

Referenced by ExecEndHashJoin(), and ExecReScanHashJoin().

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

◆ ExecHashTableDetach()

void ExecHashTableDetach ( HashJoinTable  hashtable)

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

3113 {
3114  if (hashtable->parallel_state)
3115  {
3116  ParallelHashJoinState *pstate = hashtable->parallel_state;
3117  int i;
3118 
3119  /* Make sure any temporary files are closed. */
3120  if (hashtable->batches)
3121  {
3122  for (i = 0; i < hashtable->nbatch; ++i)
3123  {
3124  sts_end_write(hashtable->batches[i].inner_tuples);
3125  sts_end_write(hashtable->batches[i].outer_tuples);
3128  }
3129  }
3130 
3131  /* If we're last to detach, clean up shared memory. */
3132  if (BarrierDetach(&pstate->build_barrier))
3133  {
3134  if (DsaPointerIsValid(pstate->batches))
3135  {
3136  dsa_free(hashtable->area, pstate->batches);
3137  pstate->batches = InvalidDsaPointer;
3138  }
3139  }
3140 
3141  hashtable->parallel_state = NULL;
3142  }
3143 }
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:355
dsa_pointer batches
Definition: hashjoin.h:236
void sts_end_parallel_scan(SharedTuplestoreAccessor *accessor)
ParallelHashJoinState * parallel_state
Definition: hashjoin.h:356
ParallelHashJoinBatchAccessor * batches
Definition: hashjoin.h:357
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:812
int i
void sts_end_write(SharedTuplestoreAccessor *accessor)

◆ ExecHashTableDetachBatch()

void ExecHashTableDetachBatch ( HashJoinTable  hashtable)

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

3056 {
3057  if (hashtable->parallel_state != NULL &&
3058  hashtable->curbatch >= 0)
3059  {
3060  int curbatch = hashtable->curbatch;
3061  ParallelHashJoinBatch *batch = hashtable->batches[curbatch].shared;
3062 
3063  /* Make sure any temporary files are closed. */
3064  sts_end_parallel_scan(hashtable->batches[curbatch].inner_tuples);
3065  sts_end_parallel_scan(hashtable->batches[curbatch].outer_tuples);
3066 
3067  /* Detach from the batch we were last working on. */
3069  {
3070  /*
3071  * Technically we shouldn't access the barrier because we're no
3072  * longer attached, but since there is no way it's moving after
3073  * this point it seems safe to make the following assertion.
3074  */
3076 
3077  /* Free shared chunks and buckets. */
3078  while (DsaPointerIsValid(batch->chunks))
3079  {
3080  HashMemoryChunk chunk =
3081  dsa_get_address(hashtable->area, batch->chunks);
3082  dsa_pointer next = chunk->next.shared;
3083 
3084  dsa_free(hashtable->area, batch->chunks);
3085  batch->chunks = next;
3086  }
3087  if (DsaPointerIsValid(batch->buckets))
3088  {
3089  dsa_free(hashtable->area, batch->buckets);
3090  batch->buckets = InvalidDsaPointer;
3091  }
3092  }
3093 
3094  /*
3095  * Track the largest batch we've been attached to. Though each
3096  * backend might see a different subset of batches, explain.c will
3097  * scan the results from all backends to find the largest value.
3098  */
3099  hashtable->spacePeak =
3100  Max(hashtable->spacePeak,
3101  batch->size + sizeof(dsa_pointer_atomic) * hashtable->nbuckets);
3102 
3103  /* Remember that we are not attached to a batch. */
3104  hashtable->curbatch = -1;
3105  }
3106 }
SharedTuplestoreAccessor * outer_tuples
Definition: hashjoin.h:209
#define PHJ_BATCH_DONE
Definition: hashjoin.h:268
static int32 next
Definition: blutils.c:210
#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:355
dsa_pointer shared
Definition: hashjoin.h:127
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:924
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:356
ParallelHashJoinBatchAccessor * batches
Definition: hashjoin.h:357
#define Max(x, y)
Definition: c.h:840
#define Assert(condition)
Definition: c.h:688
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:812
dsa_pointer buckets
Definition: hashjoin.h:153

◆ ExecHashTableInsert()

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

Definition at line 1588 of file nodeHash.c.

References Assert, HashJoinTableData::buckets, HashJoinTableData::curbatch, dense_alloc(), ExecFetchSlotMinimalTuple(), ExecHashGetBucketAndBatch(), ExecHashIncreaseNumBatches(), ExecHashJoinSaveTuple(), HashJoinTupleData::hashvalue, 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().

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

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

Referenced by ExecHashJoinNewBatch().

2114 {
2115  MemoryContext oldcxt;
2116  int nbuckets = hashtable->nbuckets;
2117 
2118  /*
2119  * Release all the hash buckets and tuples acquired in the prior pass, and
2120  * reinitialize the context for a new pass.
2121  */
2122  MemoryContextReset(hashtable->batchCxt);
2123  oldcxt = MemoryContextSwitchTo(hashtable->batchCxt);
2124 
2125  /* Reallocate and reinitialize the hash bucket headers. */
2126  hashtable->buckets.unshared = (HashJoinTuple *)
2127  palloc0(nbuckets * sizeof(HashJoinTuple));
2128 
2129  hashtable->spaceUsed = 0;
2130 
2131  MemoryContextSwitchTo(oldcxt);
2132 
2133  /* Forget the chunks (the memory was freed by the context reset above). */
2134  hashtable->chunks = NULL;
2135 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:134
MemoryContext batchCxt
Definition: hashjoin.h:348
void * palloc0(Size size)
Definition: mcxt.c:864
union HashJoinTableData::@97 buckets
HashMemoryChunk chunks
Definition: hashjoin.h:351
struct HashJoinTupleData ** unshared
Definition: hashjoin.h:297

◆ ExecHashTableResetMatchFlags()

void ExecHashTableResetMatchFlags ( HashJoinTable  hashtable)

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

2143 {
2144  HashJoinTuple tuple;
2145  int i;
2146 
2147  /* Reset all flags in the main table ... */
2148  for (i = 0; i < hashtable->nbuckets; i++)
2149  {
2150  for (tuple = hashtable->buckets.unshared[i]; tuple != NULL;
2151  tuple = tuple->next.unshared)
2153  }
2154 
2155  /* ... and the same for the skew buckets, if any */
2156  for (i = 0; i < hashtable->nSkewBuckets; i++)
2157  {
2158  int j = hashtable->skewBucketNums[i];
2159  HashSkewBucket *skewBucket = hashtable->skewBucket[j];
2160 
2161  for (tuple = skewBucket->tuples; tuple != NULL; tuple = tuple->next.unshared)
2163  }
2164 }
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:532
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(), ExecInitNode(), ExecInitQual(), ExecInitResultTupleSlotTL(), PlanState::ExecProcNode, HashState::hashkeys, HashState::hashtable, makeNode, NIL, outerPlan, outerPlanState, PlanState::plan, Hash::plan, HashState::ps, PlanState::ps_ProjInfo, Plan::qual, PlanState::qual, and PlanState::state.

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  */
385  ExecInitResultTupleSlotTL(estate, &hashstate->ps);
386  hashstate->ps.ps_ProjInfo = NULL;
387 
388  /*
389  * initialize child expressions
390  */
391  hashstate->ps.qual =
392  ExecInitQual(node->plan.qual, (PlanState *) hashstate);
393 
394  return hashstate;
395 }
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:145
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:903
HashJoinTable hashtable
Definition: execnodes.h:2059
EState * state
Definition: execnodes.h:870
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:204
#define EXEC_FLAG_BACKWARD
Definition: executor.h:61
#define outerPlanState(node)
Definition: execnodes.h:914
List * hashkeys
Definition: execnodes.h:2060
PlanState ps
Definition: execnodes.h:2058
#define outerPlan(node)
Definition: plannodes.h:174
static TupleTableSlot * ExecHash(PlanState *pstate)
Definition: nodeHash.c:91
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:874
void ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate)
Definition: execTuples.c:870
Plan * plan
Definition: execnodes.h:868
#define makeNode(_type_)
Definition: nodes.h:561
#define Assert(condition)
Definition: c.h:688
#define EXEC_FLAG_MARK
Definition: executor.h:62
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:425
ExprState * qual
Definition: execnodes.h:886
Plan plan
Definition: plannodes.h:885
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:139

◆ ExecParallelHashTableAlloc()

void ExecParallelHashTableAlloc ( HashJoinTable  hashtable,
int  batchno 
)

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

3036 {
3037  ParallelHashJoinBatch *batch = hashtable->batches[batchno].shared;
3038  dsa_pointer_atomic *buckets;
3039  int nbuckets = hashtable->parallel_state->nbuckets;
3040  int i;
3041 
3042  batch->buckets =
3043  dsa_allocate(hashtable->area, sizeof(dsa_pointer_atomic) * nbuckets);
3044  buckets = (dsa_pointer_atomic *)
3045  dsa_get_address(hashtable->area, batch->buckets);
3046  for (i = 0; i < nbuckets; ++i)
3048 }
#define InvalidDsaPointer
Definition: dsa.h:78
dsa_area * area
Definition: hashjoin.h:355
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:924
ParallelHashJoinState * parallel_state
Definition: hashjoin.h:356
ParallelHashJoinBatchAccessor * batches
Definition: hashjoin.h:357
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 1673 of file nodeHash.c.

References Assert, BarrierPhase(), HashJoinTableData::batches, HashJoinTableData::buckets, ParallelHashJoinState::build_barrier, ExecFetchSlotMinimalTuple(), ExecHashGetBucketAndBatch(), ExecParallelHashPushTuple(), ExecParallelHashTupleAlloc(), ExecParallelHashTuplePrealloc(), HashJoinTupleData::hashvalue, 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().

1676 {
1678  dsa_pointer shared;
1679  int bucketno;
1680  int batchno;
1681 
1682 retry:
1683  ExecHashGetBucketAndBatch(hashtable, hashvalue, &bucketno, &batchno);
1684 
1685  if (batchno == 0)
1686  {
1687  HashJoinTuple hashTuple;
1688 
1689  /* Try to load it into memory. */
1692  hashTuple = ExecParallelHashTupleAlloc(hashtable,
1693  HJTUPLE_OVERHEAD + tuple->t_len,
1694  &shared);
1695  if (hashTuple == NULL)
1696  goto retry;
1697 
1698  /* Store the hash value in the HashJoinTuple header. */
1699  hashTuple->hashvalue = hashvalue;
1700  memcpy(HJTUPLE_MINTUPLE(hashTuple), tuple, tuple->t_len);
1701 
1702  /* Push it onto the front of the bucket's list */
1703  ExecParallelHashPushTuple(&hashtable->buckets.shared[bucketno],
1704  hashTuple, shared);
1705  }
1706  else
1707  {
1708  size_t tuple_size = MAXALIGN(HJTUPLE_OVERHEAD + tuple->t_len);
1709 
1710  Assert(batchno > 0);
1711 
1712  /* Try to preallocate space in the batch if necessary. */
1713  if (hashtable->batches[batchno].preallocated < tuple_size)
1714  {
1715  if (!ExecParallelHashTuplePrealloc(hashtable, batchno, tuple_size))
1716  goto retry;
1717  }
1718 
1719  Assert(hashtable->batches[batchno].preallocated >= tuple_size);
1720  hashtable->batches[batchno].preallocated -= tuple_size;
1721  sts_puttuple(hashtable->batches[batchno].inner_tuples, &hashvalue,
1722  tuple);
1723  }
1724  ++hashtable->batches[batchno].ntuples;
1725 }
dsa_pointer_atomic * shared
Definition: hashjoin.h:299
void sts_puttuple(SharedTuplestoreAccessor *accessor, void *meta_data, MinimalTuple tuple)
MinimalTuple ExecFetchSlotMinimalTuple(TupleTableSlot *slot)
Definition: execTuples.c:688
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:1874
static bool ExecParallelHashTuplePrealloc(HashJoinTable hashtable, int batchno, size_t size)
Definition: nodeHash.c:3259
ParallelHashJoinState * parallel_state
Definition: hashjoin.h:356
#define HJTUPLE_OVERHEAD
Definition: hashjoin.h:79
ParallelHashJoinBatchAccessor * batches
Definition: hashjoin.h:357
#define HJTUPLE_MINTUPLE(hjtup)
Definition: hashjoin.h:80
#define Assert(condition)
Definition: c.h:688
int BarrierPhase(Barrier *barrier)
Definition: barrier.c:243
#define MAXALIGN(LEN)
Definition: c.h:641
union HashJoinTableData::@97 buckets
static void ExecParallelHashPushTuple(dsa_pointer_atomic *head, HashJoinTuple tuple, dsa_pointer tuple_shared)
Definition: nodeHash.c:3179
#define PHJ_BUILD_HASHING_INNER
Definition: hashjoin.h:259
static HashJoinTuple ExecParallelHashTupleAlloc(HashJoinTable hashtable, size_t size, dsa_pointer *shared)
Definition: nodeHash.c:2729
uint32 hashvalue
Definition: hashjoin.h:75

◆ ExecParallelHashTableInsertCurrentBatch()

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

Definition at line 1734 of file nodeHash.c.

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

Referenced by ExecParallelHashJoinNewBatch().

1737 {
1739  HashJoinTuple hashTuple;
1740  dsa_pointer shared;
1741  int batchno;
1742  int bucketno;
1743 
1744  ExecHashGetBucketAndBatch(hashtable, hashvalue, &bucketno, &batchno);
1745  Assert(batchno == hashtable->curbatch);
1746  hashTuple = ExecParallelHashTupleAlloc(hashtable,
1747  HJTUPLE_OVERHEAD + tuple->t_len,
1748  &shared);
1749  hashTuple->hashvalue = hashvalue;
1750  memcpy(HJTUPLE_MINTUPLE(hashTuple), tuple, tuple->t_len);
1752  ExecParallelHashPushTuple(&hashtable->buckets.shared[bucketno],
1753  hashTuple, shared);
1754 }
dsa_pointer_atomic * shared
Definition: hashjoin.h:299
MinimalTuple ExecFetchSlotMinimalTuple(TupleTableSlot *slot)
Definition: execTuples.c:688
uint64 dsa_pointer
Definition: dsa.h:62
void ExecHashGetBucketAndBatch(HashJoinTable hashtable, uint32 hashvalue, int *bucketno, int *batchno)
Definition: nodeHash.c:1874
#define HJTUPLE_OVERHEAD
Definition: hashjoin.h:79
#define HJTUPLE_MINTUPLE(hjtup)
Definition: hashjoin.h:80
#define Assert(condition)
Definition: c.h:688
#define HeapTupleHeaderClearMatch(tup)
Definition: htup_details.h:532
union HashJoinTableData::@97 buckets
static void ExecParallelHashPushTuple(dsa_pointer_atomic *head, HashJoinTuple tuple, dsa_pointer tuple_shared)
Definition: nodeHash.c:3179
static HashJoinTuple ExecParallelHashTupleAlloc(HashJoinTable hashtable, size_t size, dsa_pointer *shared)
Definition: nodeHash.c:2729
uint32 hashvalue
Definition: hashjoin.h:75

◆ ExecParallelHashTableSetCurrentBatch()

void ExecParallelHashTableSetCurrentBatch ( HashJoinTable  hashtable,
int  batchno 
)

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

3198 {
3199  Assert(hashtable->batches[batchno].shared->buckets != InvalidDsaPointer);
3200 
3201  hashtable->curbatch = batchno;
3202  hashtable->buckets.shared = (dsa_pointer_atomic *)
3203  dsa_get_address(hashtable->area,
3204  hashtable->batches[batchno].shared->buckets);
3205  hashtable->nbuckets = hashtable->parallel_state->nbuckets;
3206  hashtable->log2_nbuckets = my_log2(hashtable->nbuckets);
3207  hashtable->current_chunk = NULL;
3209  hashtable->batches[batchno].at_least_one_chunk = false;
3210 }
dsa_pointer current_chunk_shared
Definition: hashjoin.h:358
dsa_pointer_atomic * shared
Definition: hashjoin.h:299
#define InvalidDsaPointer
Definition: dsa.h:78
dsa_area * area
Definition: hashjoin.h:355
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:924
int my_log2(long num)
Definition: dynahash.c:1716
ParallelHashJoinState * parallel_state
Definition: hashjoin.h:356
ParallelHashJoinBatchAccessor * batches
Definition: hashjoin.h:357
#define Assert(condition)
Definition: c.h:688
union HashJoinTableData::@97 buckets
ParallelHashJoinBatch * shared
Definition: hashjoin.h:197
HashMemoryChunk current_chunk
Definition: hashjoin.h:354
dsa_pointer buckets
Definition: hashjoin.h:153

◆ ExecParallelScanHashBucket()

bool ExecParallelScanHashBucket ( HashJoinState hjstate,
ExprContext econtext 
)

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

1969 {
1970  ExprState *hjclauses = hjstate->hashclauses;
1971  HashJoinTable hashtable = hjstate->hj_HashTable;
1972  HashJoinTuple hashTuple = hjstate->hj_CurTuple;
1973  uint32 hashvalue = hjstate->hj_CurHashValue;
1974 
1975  /*
1976  * hj_CurTuple is the address of the tuple last returned from the current
1977  * bucket, or NULL if it's time to start scanning a new bucket.
1978  */
1979  if (hashTuple != NULL)
1980  hashTuple = ExecParallelHashNextTuple(hashtable, hashTuple);
1981  else
1982  hashTuple = ExecParallelHashFirstTuple(hashtable,
1983  hjstate->hj_CurBucketNo);
1984 
1985  while (hashTuple != NULL)
1986  {
1987  if (hashTuple->hashvalue == hashvalue)
1988  {
1989  TupleTableSlot *inntuple;
1990 
1991  /* insert hashtable's tuple into exec slot so ExecQual sees it */
1992  inntuple = ExecStoreMinimalTuple(HJTUPLE_MINTUPLE(hashTuple),
1993  hjstate->hj_HashTupleSlot,
1994  false); /* do not pfree */
1995  econtext->ecxt_innertuple = inntuple;
1996 
1997  if (ExecQualAndReset(hjclauses, econtext))
1998  {
1999  hjstate->hj_CurTuple = hashTuple;
2000  return true;
2001  }
2002  }
2003 
2004  hashTuple = ExecParallelHashNextTuple(hashtable, hashTuple);
2005  }
2006 
2007  /*
2008  * no match
2009  */
2010  return false;
2011 }
TupleTableSlot * ExecStoreMinimalTuple(MinimalTuple mtup, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:420
uint32 hj_CurHashValue
Definition: execnodes.h:1730
HashJoinTuple hj_CurTuple
Definition: execnodes.h:1733
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:212
unsigned int uint32
Definition: c.h:314
int hj_CurBucketNo
Definition: execnodes.h:1731
static bool ExecQualAndReset(ExprState *state, ExprContext *econtext)
Definition: executor.h:389
#define HJTUPLE_MINTUPLE(hjtup)
Definition: hashjoin.h:80
static HashJoinTuple ExecParallelHashFirstTuple(HashJoinTable table, int bucketno)
Definition: nodeHash.c:3149
TupleTableSlot * hj_HashTupleSlot
Definition: execnodes.h:1735
static HashJoinTuple ExecParallelHashNextTuple(HashJoinTable table, HashJoinTuple tuple)
Definition: nodeHash.c:3165
HashJoinTable hj_HashTable
Definition: execnodes.h:1729
uint32 hashvalue
Definition: hashjoin.h:75
ExprState * hashclauses
Definition: execnodes.h:1725

◆ ExecPrepHashTableForUnmatched()

void ExecPrepHashTableForUnmatched ( HashJoinState hjstate)

Definition at line 2018 of file nodeHash.c.

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

Referenced by ExecHashJoinImpl().

2019 {
2020  /*----------
2021  * During this scan we use the HashJoinState fields as follows:
2022  *
2023  * hj_CurBucketNo: next regular bucket to scan
2024  * hj_CurSkewBucketNo: next skew bucket (an index into skewBucketNums)
2025  * hj_CurTuple: last tuple returned, or NULL to start next bucket
2026  *----------
2027  */
2028  hjstate->hj_CurBucketNo = 0;
2029  hjstate->hj_CurSkewBucketNo = 0;
2030  hjstate->hj_CurTuple = NULL;
2031 }
int hj_CurSkewBucketNo
Definition: execnodes.h:1732
HashJoinTuple hj_CurTuple
Definition: execnodes.h:1733
int hj_CurBucketNo
Definition: execnodes.h:1731

◆ ExecReScanHash()

void ExecReScanHash ( HashState node)

Definition at line 2168 of file nodeHash.c.

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

Referenced by ExecReScan().

2169 {
2170  /*
2171  * if chgParam of subnode is not null then plan will be re-scanned by
2172  * first ExecProcNode.
2173  */
2174  if (node->ps.lefttree->chgParam == NULL)
2175  ExecReScan(node->ps.lefttree);
2176 }
void ExecReScan(PlanState *node)
Definition: execAmi.c:76
struct PlanState * lefttree
Definition: execnodes.h:887
PlanState ps
Definition: execnodes.h:2058
Bitmapset * chgParam
Definition: execnodes.h:896

◆ ExecScanHashBucket()

bool ExecScanHashBucket ( HashJoinState hjstate,
ExprContext econtext 
)

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

1908 {
1909  ExprState *hjclauses = hjstate->hashclauses;
1910  HashJoinTable hashtable = hjstate->hj_HashTable;
1911  HashJoinTuple hashTuple = hjstate->hj_CurTuple;
1912  uint32 hashvalue = hjstate->hj_CurHashValue;
1913 
1914  /*
1915  * hj_CurTuple is the address of the tuple last returned from the current
1916  * bucket, or NULL if it's time to start scanning a new bucket.
1917  *
1918  * If the tuple hashed to a skew bucket then scan the skew bucket
1919  * otherwise scan the standard hashtable bucket.
1920  */
1921  if (hashTuple != NULL)
1922  hashTuple = hashTuple->next.unshared;
1923  else if (hjstate->hj_CurSkewBucketNo != INVALID_SKEW_BUCKET_NO)
1924  hashTuple = hashtable->skewBucket[hjstate->hj_CurSkewBucketNo]->tuples;
1925  else
1926  hashTuple = hashtable->buckets.unshared[hjstate->hj_CurBucketNo];
1927 
1928  while (hashTuple != NULL)
1929  {
1930  if (hashTuple->hashvalue == hashvalue)
1931  {
1932  TupleTableSlot *inntuple;
1933 
1934  /* insert hashtable's tuple into exec slot so ExecQual sees it */
1935  inntuple = ExecStoreMinimalTuple(HJTUPLE_MINTUPLE(hashTuple),
1936  hjstate->hj_HashTupleSlot,
1937  false); /* do not pfree */
1938  econtext->ecxt_innertuple = inntuple;
1939 
1940  if (ExecQualAndReset(hjclauses, econtext))
1941  {
1942  hjstate->hj_CurTuple = hashTuple;
1943  return true;
1944  }
1945  }
1946 
1947  hashTuple = hashTuple->next.unshared;
1948  }
1949 
1950  /*
1951  * no match
1952  */
1953  return false;
1954 }
#define INVALID_SKEW_BUCKET_NO
Definition: hashjoin.h:109
TupleTableSlot * ExecStoreMinimalTuple(MinimalTuple mtup, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:420
union HashJoinTupleData::@95 next
uint32 hj_CurHashValue
Definition: execnodes.h:1730
int hj_CurSkewBucketNo
Definition: execnodes.h:1732
struct HashJoinTupleData * unshared
Definition: hashjoin.h:72
HashJoinTuple hj_CurTuple
Definition: execnodes.h:1733
HashJoinTuple tuples
Definition: hashjoin.h:105
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:212
unsigned int uint32
Definition: c.h:314
int hj_CurBucketNo
Definition: execnodes.h:1731
static bool ExecQualAndReset(ExprState *state, ExprContext *econtext)
Definition: executor.h:389
HashSkewBucket ** skewBucket
Definition: hashjoin.h:305
#define HJTUPLE_MINTUPLE(hjtup)
Definition: hashjoin.h:80
union HashJoinTableData::@97 buckets
TupleTableSlot * hj_HashTupleSlot
Definition: execnodes.h:1735
HashJoinTable hj_HashTable
Definition: execnodes.h:1729
struct HashJoinTupleData ** unshared
Definition: hashjoin.h:297
uint32 hashvalue
Definition: hashjoin.h:75
ExprState * hashclauses
Definition: execnodes.h:1725

◆ ExecScanHashTableForUnmatched()

bool ExecScanHashTableForUnmatched ( HashJoinState hjstate,
ExprContext econtext 
)

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

2043 {
2044  HashJoinTable hashtable = hjstate->hj_HashTable;
2045  HashJoinTuple hashTuple = hjstate->hj_CurTuple;
2046 
2047  for (;;)
2048  {
2049  /*
2050  * hj_CurTuple is the address of the tuple last returned from the
2051  * current bucket, or NULL if it's time to start scanning a new
2052  * bucket.
2053  */
2054  if (hashTuple != NULL)
2055  hashTuple = hashTuple->next.unshared;
2056  else if (hjstate->hj_CurBucketNo < hashtable->nbuckets)
2057  {
2058  hashTuple = hashtable->buckets.unshared[hjstate->hj_CurBucketNo];
2059  hjstate->hj_CurBucketNo++;
2060  }
2061  else if (hjstate->hj_CurSkewBucketNo < hashtable->nSkewBuckets)
2062  {
2063  int j = hashtable->skewBucketNums[hjstate->hj_CurSkewBucketNo];
2064 
2065  hashTuple = hashtable->skewBucket[j]->tuples;
2066  hjstate->hj_CurSkewBucketNo++;
2067  }
2068  else
2069  break; /* finished all buckets */
2070 
2071  while (hashTuple != NULL)
2072  {
2073  if (!HeapTupleHeaderHasMatch(HJTUPLE_MINTUPLE(hashTuple)))
2074  {
2075  TupleTableSlot *inntuple;
2076 
2077  /* insert hashtable's tuple into exec slot */
2078  inntuple = ExecStoreMinimalTuple(HJTUPLE_MINTUPLE(hashTuple),
2079  hjstate->hj_HashTupleSlot,
2080  false); /* do not pfree */
2081  econtext->ecxt_innertuple = inntuple;
2082 
2083  /*
2084  * Reset temp memory each time; although this function doesn't
2085  * do any qual eval, the caller will, so let's keep it
2086  * parallel to ExecScanHashBucket.
2087  */
2088  ResetExprContext(econtext);
2089 
2090  hjstate->hj_CurTuple = hashTuple;
2091  return true;
2092  }
2093 
2094  hashTuple = hashTuple->next.unshared;
2095  }
2096 
2097  /* allow this loop to be cancellable */
2099  }
2100 
2101  /*
2102  * no more unmatched tuples
2103  */
2104  return false;
2105 }
TupleTableSlot * ExecStoreMinimalTuple(MinimalTuple mtup, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:420
union HashJoinTupleData::@95 next
int * skewBucketNums
Definition: hashjoin.h:308
int hj_CurSkewBucketNo
Definition: execnodes.h:1732
struct HashJoinTupleData * unshared
Definition: hashjoin.h:72
HashJoinTuple hj_CurTuple
Definition: execnodes.h:1733
HashJoinTuple tuples
Definition: hashjoin.h:105
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:212
int hj_CurBucketNo
Definition: execnodes.h:1731
HashSkewBucket ** skewBucket
Definition: hashjoin.h:305
#define HJTUPLE_MINTUPLE(hjtup)
Definition: hashjoin.h:80
#define HeapTupleHeaderHasMatch(tup)
Definition: htup_details.h:522
union HashJoinTableData::@97 buckets
TupleTableSlot * hj_HashTupleSlot
Definition: execnodes.h:1735
HashJoinTable hj_HashTable
Definition: execnodes.h:1729
struct HashJoinTupleData ** unshared
Definition: hashjoin.h:297
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
#define ResetExprContext(econtext)
Definition: executor.h:484

◆ ExecShutdownHash()

void ExecShutdownHash ( HashState node)

Definition at line 2604 of file nodeHash.c.

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

Referenced by ExecShutdownNode().

2605 {
2606  if (node->hinstrument && node->hashtable)
2608 }
void ExecHashGetInstrumentation(HashInstrumentation *instrument, HashJoinTable hashtable)
Definition: nodeHash.c:2635
HashJoinTable hashtable
Definition: execnodes.h:2059
HashInstrumentation * hinstrument
Definition: execnodes.h:2064

◆ 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:2067
void InstrStopNode(Instrumentation *instr, double nTuples)
Definition: instrument.c:80
Instrumentation * instrument
Definition: execnodes.h:878
HashJoinTable hashtable
Definition: execnodes.h:2059
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:2058
static void MultiExecParallelHash(HashState *node)
Definition: nodeHash.c:213