mirror of
https://github.com/postgres/postgres.git
synced 2026-02-03 20:40:14 -05:00
Full and right outer joins were not supported in the initial implementation of Parallel Hash Join because of deadlock hazards (see discussion). Therefore FULL JOIN inhibited parallelism, as the other join strategies can't do that in parallel either. Add a new PHJ phase PHJ_BATCH_SCAN that scans for unmatched tuples on the inner side of one batch's hash table. For now, sidestep the deadlock problem by terminating parallelism there. The last process to arrive at that phase emits the unmatched tuples, while others detach and are free to go and work on other batches, if there are any, but otherwise they finish the join early. That unfairness is considered acceptable for now, because it's better than no parallelism at all. The build and probe phases are run in parallel, and the new scan-for-unmatched phase, while serial, is usually applied to the smaller of the two relations and is either limited by some multiple of work_mem, or it's too big and is partitioned into batches and then the situation is improved by batch-level parallelism. Author: Melanie Plageman <melanieplageman@gmail.com> Author: Thomas Munro <thomas.munro@gmail.com> Reviewed-by: Thomas Munro <thomas.munro@gmail.com> Discussion: https://postgr.es/m/CA%2BhUKG%2BA6ftXPz4oe92%2Bx8Er%2BxpGZqto70-Q_ERwRaSyA%3DafNg%40mail.gmail.com
82 lines
3.3 KiB
C
82 lines
3.3 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* nodeHash.h
|
|
* prototypes for nodeHash.c
|
|
*
|
|
*
|
|
* Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
* src/include/executor/nodeHash.h
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#ifndef NODEHASH_H
|
|
#define NODEHASH_H
|
|
|
|
#include "access/parallel.h"
|
|
#include "nodes/execnodes.h"
|
|
|
|
struct SharedHashJoinBatch;
|
|
|
|
extern HashState *ExecInitHash(Hash *node, EState *estate, int eflags);
|
|
extern Node *MultiExecHash(HashState *node);
|
|
extern void ExecEndHash(HashState *node);
|
|
extern void ExecReScanHash(HashState *node);
|
|
|
|
extern HashJoinTable ExecHashTableCreate(HashState *state, List *hashOperators, List *hashCollations,
|
|
bool keepNulls);
|
|
extern void ExecParallelHashTableAlloc(HashJoinTable hashtable,
|
|
int batchno);
|
|
extern void ExecHashTableDestroy(HashJoinTable hashtable);
|
|
extern void ExecHashTableDetach(HashJoinTable hashtable);
|
|
extern void ExecHashTableDetachBatch(HashJoinTable hashtable);
|
|
extern void ExecParallelHashTableSetCurrentBatch(HashJoinTable hashtable,
|
|
int batchno);
|
|
|
|
extern void ExecHashTableInsert(HashJoinTable hashtable,
|
|
TupleTableSlot *slot,
|
|
uint32 hashvalue);
|
|
extern void ExecParallelHashTableInsert(HashJoinTable hashtable,
|
|
TupleTableSlot *slot,
|
|
uint32 hashvalue);
|
|
extern void ExecParallelHashTableInsertCurrentBatch(HashJoinTable hashtable,
|
|
TupleTableSlot *slot,
|
|
uint32 hashvalue);
|
|
extern bool ExecHashGetHashValue(HashJoinTable hashtable,
|
|
ExprContext *econtext,
|
|
List *hashkeys,
|
|
bool outer_tuple,
|
|
bool keep_nulls,
|
|
uint32 *hashvalue);
|
|
extern void ExecHashGetBucketAndBatch(HashJoinTable hashtable,
|
|
uint32 hashvalue,
|
|
int *bucketno,
|
|
int *batchno);
|
|
extern bool ExecScanHashBucket(HashJoinState *hjstate, ExprContext *econtext);
|
|
extern bool ExecParallelScanHashBucket(HashJoinState *hjstate, ExprContext *econtext);
|
|
extern void ExecPrepHashTableForUnmatched(HashJoinState *hjstate);
|
|
extern bool ExecParallelPrepHashTableForUnmatched(HashJoinState *hjstate);
|
|
extern bool ExecScanHashTableForUnmatched(HashJoinState *hjstate,
|
|
ExprContext *econtext);
|
|
extern bool ExecParallelScanHashTableForUnmatched(HashJoinState *hjstate,
|
|
ExprContext *econtext);
|
|
extern void ExecHashTableReset(HashJoinTable hashtable);
|
|
extern void ExecHashTableResetMatchFlags(HashJoinTable hashtable);
|
|
extern void ExecChooseHashTableSize(double ntuples, int tupwidth, bool useskew,
|
|
bool try_combined_hash_mem,
|
|
int parallel_workers,
|
|
size_t *space_allowed,
|
|
int *numbuckets,
|
|
int *numbatches,
|
|
int *num_skew_mcvs);
|
|
extern int ExecHashGetSkewBucket(HashJoinTable hashtable, uint32 hashvalue);
|
|
extern void ExecHashEstimate(HashState *node, ParallelContext *pcxt);
|
|
extern void ExecHashInitializeDSM(HashState *node, ParallelContext *pcxt);
|
|
extern void ExecHashInitializeWorker(HashState *node, ParallelWorkerContext *pwcxt);
|
|
extern void ExecHashRetrieveInstrumentation(HashState *node);
|
|
extern void ExecShutdownHash(HashState *node);
|
|
extern void ExecHashAccumInstrumentation(HashInstrumentation *instrument,
|
|
HashJoinTable hashtable);
|
|
|
|
#endif /* NODEHASH_H */
|