]> granicus.if.org Git - postgresql/commitdiff
Improve EXPLAIN to print the grouping columns in Agg and Group nodes.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 12 Dec 2013 16:24:38 +0000 (11:24 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 12 Dec 2013 16:24:38 +0000 (11:24 -0500)
Per request from Kevin Grittner.

doc/src/sgml/ref/explain.sgml
src/backend/commands/explain.c
src/test/regress/expected/aggregates.out
src/test/regress/expected/matview.out
src/test/regress/expected/union.out
src/test/regress/expected/window.out

index 959095679a92e78653a9415b7564e4101c5edcee..35264dcc72cf44023a315e0d4b4d500d0bea1320 100644 (file)
@@ -395,13 +395,14 @@ PREPARE query(int, int) AS SELECT sum(bar) FROM test
 
 EXPLAIN ANALYZE EXECUTE query(100, 200);
 
-                                                       QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------
- HashAggregate  (cost=39.53..39.53 rows=1 width=8) (actual time=0.661..0.672 rows=7 loops=1)
-   -&gt;  Index Scan using test_pkey on test  (cost=0.00..32.97 rows=1311 width=8) (actual time=0.050..0.395 rows=99 loops=1)
+                                                       QUERY PLAN                                                       
+------------------------------------------------------------------------------------------------------------------------
+ HashAggregate  (cost=9.54..9.54 rows=1 width=8) (actual time=0.156..0.161 rows=11 loops=1)
+   Group Key: foo
+   -&gt;  Index Scan using test_pkey on test  (cost=0.29..9.29 rows=50 width=8) (actual time=0.039..0.091 rows=99 loops=1)
          Index Cond: ((id &gt; $1) AND (id &lt; $2))
- Total runtime: 0.851 ms
-(4 rows)
+ Total runtime: 0.225 ms
+(5 rows)
 </programlisting>
   </para>
 
index bd5428de97b74ab8f4767d14a26626de237d4598..9969a251a7e065510b13e446d160df36cb61909f 100644 (file)
@@ -76,9 +76,13 @@ static void show_sort_keys(SortState *sortstate, List *ancestors,
                           ExplainState *es);
 static void show_merge_append_keys(MergeAppendState *mstate, List *ancestors,
                                           ExplainState *es);
-static void show_sort_keys_common(PlanState *planstate,
-                                         int nkeys, AttrNumber *keycols,
-                                         List *ancestors, ExplainState *es);
+static void show_agg_keys(AggState *astate, List *ancestors,
+                         ExplainState *es);
+static void show_group_keys(GroupState *gstate, List *ancestors,
+                               ExplainState *es);
+static void show_sort_group_keys(PlanState *planstate, const char *qlabel,
+                                        int nkeys, AttrNumber *keycols,
+                                        List *ancestors, ExplainState *es);
 static void show_sort_info(SortState *sortstate, ExplainState *es);
 static void show_hash_info(HashState *hashstate, ExplainState *es);
 static void show_instrumentation_count(const char *qlabel, int which,
@@ -1341,7 +1345,14 @@ ExplainNode(PlanState *planstate, List *ancestors,
                                                                                   planstate, es);
                        break;
                case T_Agg:
+                       show_agg_keys((AggState *) planstate, ancestors, es);
+                       show_upper_qual(plan->qual, "Filter", planstate, ancestors, es);
+                       if (plan->qual)
+                               show_instrumentation_count("Rows Removed by Filter", 1,
+                                                                                  planstate, es);
+                       break;
                case T_Group:
+                       show_group_keys((GroupState *) planstate, ancestors, es);
                        show_upper_qual(plan->qual, "Filter", planstate, ancestors, es);
                        if (plan->qual)
                                show_instrumentation_count("Rows Removed by Filter", 1,
@@ -1693,9 +1704,9 @@ show_sort_keys(SortState *sortstate, List *ancestors, ExplainState *es)
 {
        Sort       *plan = (Sort *) sortstate->ss.ps.plan;
 
-       show_sort_keys_common((PlanState *) sortstate,
-                                                 plan->numCols, plan->sortColIdx,
-                                                 ancestors, es);
+       show_sort_group_keys((PlanState *) sortstate, "Sort Key",
+                                                plan->numCols, plan->sortColIdx,
+                                                ancestors, es);
 }
 
 /*
@@ -1707,14 +1718,56 @@ show_merge_append_keys(MergeAppendState *mstate, List *ancestors,
 {
        MergeAppend *plan = (MergeAppend *) mstate->ps.plan;
 
-       show_sort_keys_common((PlanState *) mstate,
-                                                 plan->numCols, plan->sortColIdx,
-                                                 ancestors, es);
+       show_sort_group_keys((PlanState *) mstate, "Sort Key",
+                                                plan->numCols, plan->sortColIdx,
+                                                ancestors, es);
 }
 
+/*
+ * Show the grouping keys for an Agg node.
+ */
+static void
+show_agg_keys(AggState *astate, List *ancestors,
+                         ExplainState *es)
+{
+       Agg                *plan = (Agg *) astate->ss.ps.plan;
+
+       if (plan->numCols > 0)
+       {
+               /* The key columns refer to the tlist of the child plan */
+               ancestors = lcons(astate, ancestors);
+               show_sort_group_keys(outerPlanState(astate), "Group Key",
+                                                        plan->numCols, plan->grpColIdx,
+                                                        ancestors, es);
+               ancestors = list_delete_first(ancestors);
+       }
+}
+
+/*
+ * Show the grouping keys for a Group node.
+ */
+static void
+show_group_keys(GroupState *gstate, List *ancestors,
+                               ExplainState *es)
+{
+       Group      *plan = (Group *) gstate->ss.ps.plan;
+
+       /* The key columns refer to the tlist of the child plan */
+       ancestors = lcons(gstate, ancestors);
+       show_sort_group_keys(outerPlanState(gstate), "Group Key",
+                                                plan->numCols, plan->grpColIdx,
+                                                ancestors, es);
+       ancestors = list_delete_first(ancestors);
+}
+
+/*
+ * Common code to show sort/group keys, which are represented in plan nodes
+ * as arrays of targetlist indexes
+ */
 static void
-show_sort_keys_common(PlanState *planstate, int nkeys, AttrNumber *keycols,
-                                         List *ancestors, ExplainState *es)
+show_sort_group_keys(PlanState *planstate, const char *qlabel,
+                                        int nkeys, AttrNumber *keycols,
+                                        List *ancestors, ExplainState *es)
 {
        Plan       *plan = planstate->plan;
        List       *context;
@@ -1748,7 +1801,7 @@ show_sort_keys_common(PlanState *planstate, int nkeys, AttrNumber *keycols,
                result = lappend(result, exprstr);
        }
 
-       ExplainPropertyList("Sort Key", result, es);
+       ExplainPropertyList(qlabel, result, es);
 }
 
 /*
index c05b39cb89dad096b60076ce96fcd7adaa5fbe09..1a0ca5c5f3c109b92e5fb936efa42dafe982c81a 100644 (file)
@@ -659,12 +659,13 @@ explain (costs off)
                              QUERY PLAN                              
 ---------------------------------------------------------------------
  HashAggregate
+   Group Key: $0
    InitPlan 1 (returns $0)
      ->  Limit
            ->  Index Only Scan Backward using tenk1_unique2 on tenk1
                  Index Cond: (unique2 IS NOT NULL)
    ->  Result
-(6 rows)
+(7 rows)
 
 select distinct max(unique2) from tenk1;
  max  
@@ -806,6 +807,7 @@ explain (costs off)
                                           QUERY PLAN                                          
 ----------------------------------------------------------------------------------------------
  HashAggregate
+   Group Key: $0, $1
    InitPlan 1 (returns $0)
      ->  Limit
            ->  Merge Append
@@ -831,7 +833,7 @@ explain (costs off)
                  ->  Index Only Scan Backward using minmaxtest3i on minmaxtest3 minmaxtest3_1
                        Index Cond: (f1 IS NOT NULL)
    ->  Result
-(26 rows)
+(27 rows)
 
 select distinct min(f1), max(f1) from minmaxtest;
  min | max 
index 9ba2b9a7b48ee457b0b1561e7c459746d1873b46..31751ebd9edff4b8a45bc64fd61be579f6c2f5e0 100644 (file)
@@ -22,8 +22,9 @@ EXPLAIN (costs off)
      QUERY PLAN      
 ---------------------
  HashAggregate
+   Group Key: type
    ->  Seq Scan on t
-(2 rows)
+(3 rows)
 
 CREATE MATERIALIZED VIEW tm AS SELECT type, sum(amt) AS totamt FROM t GROUP BY type WITH NO DATA;
 SELECT relispopulated FROM pg_class WHERE oid = 'tm'::regclass;
@@ -59,8 +60,9 @@ EXPLAIN (costs off)
  Sort
    Sort Key: t.type
    ->  HashAggregate
+         Group Key: t.type
          ->  Seq Scan on t
-(4 rows)
+(5 rows)
 
 CREATE MATERIALIZED VIEW tvm AS SELECT * FROM tv ORDER BY type;
 SELECT * FROM tvm;
@@ -82,8 +84,9 @@ EXPLAIN (costs off)
 ---------------------------
  Aggregate
    ->  HashAggregate
+         Group Key: t.type
          ->  Seq Scan on t
-(3 rows)
+(4 rows)
 
 CREATE MATERIALIZED VIEW tvvm AS SELECT * FROM tvv;
 CREATE VIEW tvvmv AS SELECT * FROM tvvm;
index ae690cf9689ebc8e3e2cda052df2f0bb144f2938..6f9ee5eb47116f23ddd3dad3440f4c6e1a4541fc 100644 (file)
@@ -494,12 +494,13 @@ explain (costs off)
                     QUERY PLAN                     
 ---------------------------------------------------
  HashAggregate
+   Group Key: ((t1.a || t1.b))
    ->  Append
          ->  Index Scan using t1_ab_idx on t1
                Index Cond: ((a || b) = 'ab'::text)
          ->  Index Only Scan using t2_pkey on t2
                Index Cond: (ab = 'ab'::text)
-(6 rows)
+(7 rows)
 
 reset enable_seqscan;
 reset enable_indexscan;
@@ -552,17 +553,18 @@ SELECT * FROM
    SELECT 2 AS t, 4 AS x) ss
 WHERE x < 4
 ORDER BY x;
-           QUERY PLAN           
---------------------------------
+                       QUERY PLAN                       
+--------------------------------------------------------
  Sort
    Sort Key: ss.x
    ->  Subquery Scan on ss
          Filter: (ss.x < 4)
          ->  HashAggregate
+               Group Key: (1), (generate_series(1, 10))
                ->  Append
                      ->  Result
                      ->  Result
-(8 rows)
+(9 rows)
 
 SELECT * FROM
   (SELECT 1 AS t, generate_series(1,10) AS x
index 1e6365b4f9b4a37d0650b034c128823728ea2378..0f21fcb01da738d1d696812b84d86a5c34f286f3 100644 (file)
@@ -619,12 +619,13 @@ explain (costs off)
 select first_value(max(x)) over (), y
   from (select unique1 as x, ten+four as y from tenk1) ss
   group by y;
-          QUERY PLAN           
--------------------------------
+                 QUERY PLAN                  
+---------------------------------------------
  WindowAgg
    ->  HashAggregate
+         Group Key: (tenk1.ten + tenk1.four)
          ->  Seq Scan on tenk1
-(3 rows)
+(4 rows)
 
 -- test non-default frame specifications
 SELECT four, ten,