]> granicus.if.org Git - postgresql/commitdiff
Arrange for hash join to skip scanning the outer relation if it detects
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 22 Sep 2004 19:13:52 +0000 (19:13 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 22 Sep 2004 19:13:52 +0000 (19:13 +0000)
that the inner one is completely empty.  Per recent discussion.  Also some
cosmetic cleanups in nearby code.

src/backend/executor/nodeHash.c
src/backend/executor/nodeHashjoin.c
src/include/executor/hashjoin.h

index c4236f5fcc41175ff70e39875b1c0e8ecb148a5a..5beb6359a8317168a7358d262e8798bc88dce5d2 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.86 2004/08/29 04:12:31 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.87 2004/09/22 19:13:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -32,8 +32,8 @@
 /* ----------------------------------------------------------------
  *             ExecHash
  *
- *             build hash table for hashjoin, all do partitioning if more
- *             than one batches are required.
+ *             build hash table for hashjoin, doing partitioning if more
+ *             than one batch is required.
  * ----------------------------------------------------------------
  */
 TupleTableSlot *
@@ -81,6 +81,7 @@ ExecHash(HashState *node)
                slot = ExecProcNode(outerNode);
                if (TupIsNull(slot))
                        break;
+               hashtable->hashNonEmpty = true;
                econtext->ecxt_innertuple = slot;
                ExecHashTableInsert(hashtable, econtext, hashkeys);
                ExecClearTuple(slot);
@@ -189,7 +190,7 @@ ExecEndHash(HashState *node)
 /* ----------------------------------------------------------------
  *             ExecHashTableCreate
  *
- *             create a hashtable in shared memory for hashjoin.
+ *             create an empty hashtable data structure for hashjoin.
  * ----------------------------------------------------------------
  */
 HashJoinTable
@@ -226,12 +227,13 @@ ExecHashTableCreate(Hash *node, List *hashOperators)
         * The hashtable control block is just palloc'd from the executor's
         * per-query memory context.
         */
-       hashtable = (HashJoinTable) palloc(sizeof(HashTableData));
+       hashtable = (HashJoinTable) palloc(sizeof(HashJoinTableData));
        hashtable->nbuckets = nbuckets;
        hashtable->totalbuckets = totalbuckets;
        hashtable->buckets = NULL;
        hashtable->nbatch = nbatch;
        hashtable->curbatch = 0;
+       hashtable->hashNonEmpty = false;
        hashtable->innerBatchFile = NULL;
        hashtable->outerBatchFile = NULL;
        hashtable->innerBatchSize = NULL;
index 53215be6e9184702608b6bdcea1cef0e3f157223..294f481cdf5eda8967ade35e50eb9cc3298beab8 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.65 2004/09/17 18:28:53 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.66 2004/09/22 19:13:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -127,6 +127,17 @@ ExecHashJoin(HashJoinState *node)
                hashNode->hashtable = hashtable;
                (void) ExecProcNode((PlanState *) hashNode);
 
+               /*
+                * If the inner relation is completely empty, and we're not doing
+                * an outer join, we can quit without scanning the outer relation.
+                */
+               if (!hashtable->hashNonEmpty && node->js.jointype != JOIN_LEFT)
+               {
+                       ExecHashTableDestroy(hashtable);
+                       node->hj_HashTable = NULL;
+                       return NULL;
+               }
+
                /*
                 * Open temp files for outer batches, if needed. Note that file
                 * buffers are palloc'd in regular executor context.
@@ -138,10 +149,8 @@ ExecHashJoin(HashJoinState *node)
        }
 
        /*
-        * Now get an outer tuple and probe into the hash table for matches
+        * run the hash join process
         */
-       outerTupleSlot = node->js.ps.ps_OuterTupleSlot;
-
        for (;;)
        {
                /*
@@ -226,7 +235,7 @@ ExecHashJoin(HashJoinState *node)
                         * Only the joinquals determine MatchedOuter status, but all
                         * quals must pass to actually return the tuple.
                         */
-                       if (ExecQual(joinqual, econtext, false))
+                       if (joinqual == NIL || ExecQual(joinqual, econtext, false))
                        {
                                node->hj_MatchedOuter = true;
 
index 5dd6c5c8fe21f14d22ba02ea79fcdbcb242e4fb5..8a2eba8e0bce808c4b258d65fa380e05e3f5f909 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/executor/hashjoin.h,v 1.32 2004/08/29 04:13:06 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/executor/hashjoin.h,v 1.33 2004/09/22 19:13:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -47,7 +47,7 @@ typedef struct HashJoinTupleData
 
 typedef HashJoinTupleData *HashJoinTuple;
 
-typedef struct HashTableData
+typedef struct HashJoinTableData
 {
        int                     nbuckets;               /* buckets in use during this batch */
        int                     totalbuckets;   /* total number of (virtual) buckets */
@@ -57,6 +57,8 @@ typedef struct HashTableData
        int                     nbatch;                 /* number of batches; 0 means 1-pass join */
        int                     curbatch;               /* current batch #, or 0 during 1st pass */
 
+       bool            hashNonEmpty;   /* did inner plan produce any rows? */
+
        /*
         * all these arrays are allocated for the life of the hash join, but
         * only if nbatch > 0:
@@ -90,8 +92,8 @@ typedef struct HashTableData
 
        MemoryContext hashCxt;          /* context for whole-hash-join storage */
        MemoryContext batchCxt;         /* context for this-batch-only storage */
-} HashTableData;
+} HashJoinTableData;
 
-typedef HashTableData *HashJoinTable;
+typedef HashJoinTableData *HashJoinTable;
 
 #endif   /* HASHJOIN_H */