Augment EXPLAIN output with more details on Hash nodes.
authorRobert Haas
Mon, 1 Feb 2010 15:43:36 +0000 (15:43 +0000)
committerRobert Haas
Mon, 1 Feb 2010 15:43:36 +0000 (15:43 +0000)
We show the number of buckets, the number of batches (and also the original
number if it has changed), and the peak space used by the hash table.  Minor
executor changes to track peak space used.

src/backend/commands/explain.c
src/backend/executor/nodeHash.c
src/include/executor/hashjoin.h

index 37647e57398ff53c513b61b22ca5c0fab37399bb..8c9b060e6bdafa146b50336adc81fc35e558a171 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994-5, Regents of the University of California
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.199 2010/01/15 22:36:29 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.200 2010/02/01 15:43:35 rhaas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,6 +20,7 @@
 #include "commands/explain.h"
 #include "commands/prepare.h"
 #include "commands/trigger.h"
+#include "executor/hashjoin.h"
 #include "executor/instrument.h"
 #include "optimizer/clauses.h"
 #include "optimizer/planner.h"
@@ -67,6 +68,7 @@ static void show_upper_qual(List *qual, const char *qlabel, Plan *plan,
                ExplainState *es);
 static void show_sort_keys(Plan *sortplan, ExplainState *es);
 static void show_sort_info(SortState *sortstate, ExplainState *es);
+static void show_hash_info(HashState *hashstate, ExplainState *es);
 static const char *explain_get_index_name(Oid indexId);
 static void ExplainScanTarget(Scan *plan, ExplainState *es);
 static void ExplainMemberNodes(List *plans, PlanState **planstate,
@@ -1052,6 +1054,9 @@ ExplainNode(Plan *plan, PlanState *planstate,
                            "One-Time Filter", plan, es);
            show_upper_qual(plan->qual, "Filter", plan, es);
            break;
+       case T_Hash:
+           show_hash_info((HashState *) planstate, es);
+           break;
        default:
            break;
    }
@@ -1404,6 +1409,47 @@ show_sort_info(SortState *sortstate, ExplainState *es)
    }
 }
 
+/*
+ * Show information on hash buckets/batches.
+ */
+static void
+show_hash_info(HashState *hashstate, ExplainState *es)
+{
+   HashJoinTable hashtable;
+
+   Assert(IsA(hashstate, HashState));
+   hashtable = hashstate->hashtable;
+
+   if (hashtable)
+   {
+       long spacePeakKb = (hashtable->spacePeak + 1023) / 1024;
+       if (es->format != EXPLAIN_FORMAT_TEXT)
+       {
+           ExplainPropertyLong("Hash Buckets", hashtable->nbuckets, es);
+           ExplainPropertyLong("Hash Batches", hashtable->nbatch, es);
+           ExplainPropertyLong("Original Hash Batches",
+                               hashtable->nbatch_original, es);
+           ExplainPropertyLong("Peak Memory Usage", spacePeakKb, es);
+       }
+       else if (hashtable->nbatch_original != hashtable->nbatch)
+       {
+           appendStringInfoSpaces(es->str, es->indent * 2);
+           appendStringInfo(es->str,
+                            "Buckets: %d  Batches: %d (originally %d)  Memory Usage: %ldkB\n",
+                            hashtable->nbuckets, hashtable->nbatch,
+                            hashtable->nbatch_original, spacePeakKb);
+       }
+       else
+       {
+           appendStringInfoSpaces(es->str, es->indent * 2);
+           appendStringInfo(es->str,
+                            "Buckets: %d  Batches: %d  Memory Usage: %ldkB\n",
+                            hashtable->nbuckets, hashtable->nbatch,
+                            spacePeakKb);
+       }
+   }
+}
+
 /*
  * Fetch the name of an index in an EXPLAIN
  *
index 558a780229c37ba8546291e2026e53d4f29398f4..86bbef9be07be690762ff077e7cda52a4f00d96b 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.126 2010/01/04 02:44:39 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.127 2010/02/01 15:43:36 rhaas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -287,6 +287,7 @@ ExecHashTableCreate(Hash *node, List *hashOperators)
    hashtable->innerBatchFile = NULL;
    hashtable->outerBatchFile = NULL;
    hashtable->spaceUsed = 0;
+   hashtable->spacePeak = 0;
    hashtable->spaceAllowed = work_mem * 1024L;
    hashtable->spaceUsedSkew = 0;
    hashtable->spaceAllowedSkew =
@@ -719,6 +720,8 @@ ExecHashTableInsert(HashJoinTable hashtable,
        hashTuple->next = hashtable->buckets[bucketno];
        hashtable->buckets[bucketno] = hashTuple;
        hashtable->spaceUsed += hashTupleSize;
+       if (hashtable->spaceUsed > hashtable->spacePeak)
+           hashtable->spacePeak = hashtable->spaceUsed;
        if (hashtable->spaceUsed > hashtable->spaceAllowed)
            ExecHashIncreaseNumBatches(hashtable);
    }
@@ -1071,6 +1074,8 @@ ExecHashBuildSkewHash(HashJoinTable hashtable, Hash *node, int mcvsToUse)
            + mcvsToUse * sizeof(int);
        hashtable->spaceUsedSkew += nbuckets * sizeof(HashSkewBucket *)
            + mcvsToUse * sizeof(int);
+       if (hashtable->spaceUsed > hashtable->spacePeak)
+           hashtable->spacePeak = hashtable->spaceUsed;
 
        /*
         * Create a skew bucket for each MCV hash value.
@@ -1119,6 +1124,8 @@ ExecHashBuildSkewHash(HashJoinTable hashtable, Hash *node, int mcvsToUse)
            hashtable->nSkewBuckets++;
            hashtable->spaceUsed += SKEW_BUCKET_OVERHEAD;
            hashtable->spaceUsedSkew += SKEW_BUCKET_OVERHEAD;
+           if (hashtable->spaceUsed > hashtable->spacePeak)
+               hashtable->spacePeak = hashtable->spaceUsed;
        }
 
        free_attstatsslot(node->skewColType,
@@ -1205,6 +1212,8 @@ ExecHashSkewTableInsert(HashJoinTable hashtable,
    /* Account for space used, and back off if we've used too much */
    hashtable->spaceUsed += hashTupleSize;
    hashtable->spaceUsedSkew += hashTupleSize;
+   if (hashtable->spaceUsed > hashtable->spacePeak)
+       hashtable->spacePeak = hashtable->spaceUsed;
    while (hashtable->spaceUsedSkew > hashtable->spaceAllowedSkew)
        ExecHashRemoveNextSkewBucket(hashtable);
 
index 4e90cbd3537eae32ddf43a79a942361eab4f6b19..4ac6ae3ce84e77917eb6533756ebc47b05dd7073 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/executor/hashjoin.h,v 1.52 2010/01/02 16:58:03 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/executor/hashjoin.h,v 1.53 2010/02/01 15:43:36 rhaas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -149,6 +149,7 @@ typedef struct HashJoinTableData
 
    Size        spaceUsed;      /* memory space currently used by tuples */
    Size        spaceAllowed;   /* upper limit for space used */
+   Size        spacePeak;      /* peak space used */
    Size        spaceUsedSkew;  /* skew hash table's current space usage */
    Size        spaceAllowedSkew;       /* upper limit for skew hashtable */