Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 9fcbe2a

Browse files
committed
Arrange for hash join to skip scanning the outer relation if it detects
that the inner one is completely empty. Per recent discussion. Also some cosmetic cleanups in nearby code.
1 parent 5d9f5c2 commit 9fcbe2a

File tree

3 files changed

+27
-14
lines changed

3 files changed

+27
-14
lines changed

src/backend/executor/nodeHash.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.86 2004/08/29 04:12:31 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.87 2004/09/22 19:13:49 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -32,8 +32,8 @@
3232
/* ----------------------------------------------------------------
3333
* ExecHash
3434
*
35-
* build hash table for hashjoin, all do partitioning if more
36-
* than one batches are required.
35+
* build hash table for hashjoin, doing partitioning if more
36+
* than one batch is required.
3737
* ----------------------------------------------------------------
3838
*/
3939
TupleTableSlot *
@@ -81,6 +81,7 @@ ExecHash(HashState *node)
8181
slot = ExecProcNode(outerNode);
8282
if (TupIsNull(slot))
8383
break;
84+
hashtable->hashNonEmpty = true;
8485
econtext->ecxt_innertuple = slot;
8586
ExecHashTableInsert(hashtable, econtext, hashkeys);
8687
ExecClearTuple(slot);
@@ -189,7 +190,7 @@ ExecEndHash(HashState *node)
189190
/* ----------------------------------------------------------------
190191
* ExecHashTableCreate
191192
*
192-
* create a hashtable in shared memory for hashjoin.
193+
* create an empty hashtable data structure for hashjoin.
193194
* ----------------------------------------------------------------
194195
*/
195196
HashJoinTable
@@ -226,12 +227,13 @@ ExecHashTableCreate(Hash *node, List *hashOperators)
226227
* The hashtable control block is just palloc'd from the executor's
227228
* per-query memory context.
228229
*/
229-
hashtable = (HashJoinTable) palloc(sizeof(HashTableData));
230+
hashtable = (HashJoinTable) palloc(sizeof(HashJoinTableData));
230231
hashtable->nbuckets = nbuckets;
231232
hashtable->totalbuckets = totalbuckets;
232233
hashtable->buckets = NULL;
233234
hashtable->nbatch = nbatch;
234235
hashtable->curbatch = 0;
236+
hashtable->hashNonEmpty = false;
235237
hashtable->innerBatchFile = NULL;
236238
hashtable->outerBatchFile = NULL;
237239
hashtable->innerBatchSize = NULL;

src/backend/executor/nodeHashjoin.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.65 2004/09/17 18:28:53 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.66 2004/09/22 19:13:49 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -127,6 +127,17 @@ ExecHashJoin(HashJoinState *node)
127127
hashNode->hashtable = hashtable;
128128
(void) ExecProcNode((PlanState *) hashNode);
129129

130+
/*
131+
* If the inner relation is completely empty, and we're not doing
132+
* an outer join, we can quit without scanning the outer relation.
133+
*/
134+
if (!hashtable->hashNonEmpty && node->js.jointype != JOIN_LEFT)
135+
{
136+
ExecHashTableDestroy(hashtable);
137+
node->hj_HashTable = NULL;
138+
return NULL;
139+
}
140+
130141
/*
131142
* Open temp files for outer batches, if needed. Note that file
132143
* buffers are palloc'd in regular executor context.
@@ -138,10 +149,8 @@ ExecHashJoin(HashJoinState *node)
138149
}
139150

140151
/*
141-
* Now get an outer tuple and probe into the hash table for matches
152+
* run the hash join process
142153
*/
143-
outerTupleSlot = node->js.ps.ps_OuterTupleSlot;
144-
145154
for (;;)
146155
{
147156
/*
@@ -226,7 +235,7 @@ ExecHashJoin(HashJoinState *node)
226235
* Only the joinquals determine MatchedOuter status, but all
227236
* quals must pass to actually return the tuple.
228237
*/
229-
if (ExecQual(joinqual, econtext, false))
238+
if (joinqual == NIL || ExecQual(joinqual, econtext, false))
230239
{
231240
node->hj_MatchedOuter = true;
232241

src/include/executor/hashjoin.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/executor/hashjoin.h,v 1.32 2004/08/29 04:13:06 momjian Exp $
10+
* $PostgreSQL: pgsql/src/include/executor/hashjoin.h,v 1.33 2004/09/22 19:13:52 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -47,7 +47,7 @@ typedef struct HashJoinTupleData
4747

4848
typedef HashJoinTupleData *HashJoinTuple;
4949

50-
typedef struct HashTableData
50+
typedef struct HashJoinTableData
5151
{
5252
int nbuckets; /* buckets in use during this batch */
5353
int totalbuckets; /* total number of (virtual) buckets */
@@ -57,6 +57,8 @@ typedef struct HashTableData
5757
int nbatch; /* number of batches; 0 means 1-pass join */
5858
int curbatch; /* current batch #, or 0 during 1st pass */
5959

60+
bool hashNonEmpty; /* did inner plan produce any rows? */
61+
6062
/*
6163
* all these arrays are allocated for the life of the hash join, but
6264
* only if nbatch > 0:
@@ -90,8 +92,8 @@ typedef struct HashTableData
9092

9193
MemoryContext hashCxt; /* context for whole-hash-join storage */
9294
MemoryContext batchCxt; /* context for this-batch-only storage */
93-
} HashTableData;
95+
} HashJoinTableData;
9496

95-
typedef HashTableData *HashJoinTable;
97+
typedef HashJoinTableData *HashJoinTable;
9698

9799
#endif /* HASHJOIN_H */

0 commit comments

Comments
 (0)