Improve EXPLAIN to print the grouping columns in Agg and Group nodes.
Per request from Kevin Grittner.
This commit is contained in:
parent
8693559cac
commit
f26099057a
|
@ -395,13 +395,14 @@ PREPARE query(int, int) AS SELECT sum(bar) FROM test
|
||||||
|
|
||||||
EXPLAIN ANALYZE EXECUTE query(100, 200);
|
EXPLAIN ANALYZE EXECUTE query(100, 200);
|
||||||
|
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
-------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------
|
||||||
HashAggregate (cost=39.53..39.53 rows=1 width=8) (actual time=0.661..0.672 rows=7 loops=1)
|
HashAggregate (cost=9.54..9.54 rows=1 width=8) (actual time=0.156..0.161 rows=11 loops=1)
|
||||||
-> 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)
|
Group Key: foo
|
||||||
|
-> 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 > $1) AND (id < $2))
|
Index Cond: ((id > $1) AND (id < $2))
|
||||||
Total runtime: 0.851 ms
|
Total runtime: 0.225 ms
|
||||||
(4 rows)
|
(5 rows)
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
|
|
@ -76,9 +76,13 @@ static void show_sort_keys(SortState *sortstate, List *ancestors,
|
||||||
ExplainState *es);
|
ExplainState *es);
|
||||||
static void show_merge_append_keys(MergeAppendState *mstate, List *ancestors,
|
static void show_merge_append_keys(MergeAppendState *mstate, List *ancestors,
|
||||||
ExplainState *es);
|
ExplainState *es);
|
||||||
static void show_sort_keys_common(PlanState *planstate,
|
static void show_agg_keys(AggState *astate, List *ancestors,
|
||||||
int nkeys, AttrNumber *keycols,
|
ExplainState *es);
|
||||||
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_sort_info(SortState *sortstate, ExplainState *es);
|
||||||
static void show_hash_info(HashState *hashstate, ExplainState *es);
|
static void show_hash_info(HashState *hashstate, ExplainState *es);
|
||||||
static void show_instrumentation_count(const char *qlabel, int which,
|
static void show_instrumentation_count(const char *qlabel, int which,
|
||||||
|
@ -1341,7 +1345,14 @@ ExplainNode(PlanState *planstate, List *ancestors,
|
||||||
planstate, es);
|
planstate, es);
|
||||||
break;
|
break;
|
||||||
case T_Agg:
|
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:
|
case T_Group:
|
||||||
|
show_group_keys((GroupState *) planstate, ancestors, es);
|
||||||
show_upper_qual(plan->qual, "Filter", planstate, ancestors, es);
|
show_upper_qual(plan->qual, "Filter", planstate, ancestors, es);
|
||||||
if (plan->qual)
|
if (plan->qual)
|
||||||
show_instrumentation_count("Rows Removed by Filter", 1,
|
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;
|
Sort *plan = (Sort *) sortstate->ss.ps.plan;
|
||||||
|
|
||||||
show_sort_keys_common((PlanState *) sortstate,
|
show_sort_group_keys((PlanState *) sortstate, "Sort Key",
|
||||||
plan->numCols, plan->sortColIdx,
|
plan->numCols, plan->sortColIdx,
|
||||||
ancestors, es);
|
ancestors, es);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1707,14 +1718,56 @@ show_merge_append_keys(MergeAppendState *mstate, List *ancestors,
|
||||||
{
|
{
|
||||||
MergeAppend *plan = (MergeAppend *) mstate->ps.plan;
|
MergeAppend *plan = (MergeAppend *) mstate->ps.plan;
|
||||||
|
|
||||||
show_sort_keys_common((PlanState *) mstate,
|
show_sort_group_keys((PlanState *) mstate, "Sort Key",
|
||||||
plan->numCols, plan->sortColIdx,
|
plan->numCols, plan->sortColIdx,
|
||||||
ancestors, es);
|
ancestors, es);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Show the grouping keys for an Agg node.
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
show_sort_keys_common(PlanState *planstate, int nkeys, AttrNumber *keycols,
|
show_agg_keys(AggState *astate, List *ancestors,
|
||||||
List *ancestors, ExplainState *es)
|
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_group_keys(PlanState *planstate, const char *qlabel,
|
||||||
|
int nkeys, AttrNumber *keycols,
|
||||||
|
List *ancestors, ExplainState *es)
|
||||||
{
|
{
|
||||||
Plan *plan = planstate->plan;
|
Plan *plan = planstate->plan;
|
||||||
List *context;
|
List *context;
|
||||||
|
@ -1748,7 +1801,7 @@ show_sort_keys_common(PlanState *planstate, int nkeys, AttrNumber *keycols,
|
||||||
result = lappend(result, exprstr);
|
result = lappend(result, exprstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExplainPropertyList("Sort Key", result, es);
|
ExplainPropertyList(qlabel, result, es);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -659,12 +659,13 @@ explain (costs off)
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
HashAggregate
|
HashAggregate
|
||||||
|
Group Key: $0
|
||||||
InitPlan 1 (returns $0)
|
InitPlan 1 (returns $0)
|
||||||
-> Limit
|
-> Limit
|
||||||
-> Index Only Scan Backward using tenk1_unique2 on tenk1
|
-> Index Only Scan Backward using tenk1_unique2 on tenk1
|
||||||
Index Cond: (unique2 IS NOT NULL)
|
Index Cond: (unique2 IS NOT NULL)
|
||||||
-> Result
|
-> Result
|
||||||
(6 rows)
|
(7 rows)
|
||||||
|
|
||||||
select distinct max(unique2) from tenk1;
|
select distinct max(unique2) from tenk1;
|
||||||
max
|
max
|
||||||
|
@ -806,6 +807,7 @@ explain (costs off)
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
----------------------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------------------
|
||||||
HashAggregate
|
HashAggregate
|
||||||
|
Group Key: $0, $1
|
||||||
InitPlan 1 (returns $0)
|
InitPlan 1 (returns $0)
|
||||||
-> Limit
|
-> Limit
|
||||||
-> Merge Append
|
-> Merge Append
|
||||||
|
@ -831,7 +833,7 @@ explain (costs off)
|
||||||
-> Index Only Scan Backward using minmaxtest3i on minmaxtest3 minmaxtest3_1
|
-> Index Only Scan Backward using minmaxtest3i on minmaxtest3 minmaxtest3_1
|
||||||
Index Cond: (f1 IS NOT NULL)
|
Index Cond: (f1 IS NOT NULL)
|
||||||
-> Result
|
-> Result
|
||||||
(26 rows)
|
(27 rows)
|
||||||
|
|
||||||
select distinct min(f1), max(f1) from minmaxtest;
|
select distinct min(f1), max(f1) from minmaxtest;
|
||||||
min | max
|
min | max
|
||||||
|
|
|
@ -22,8 +22,9 @@ EXPLAIN (costs off)
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
---------------------
|
---------------------
|
||||||
HashAggregate
|
HashAggregate
|
||||||
|
Group Key: type
|
||||||
-> Seq Scan on t
|
-> 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;
|
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;
|
SELECT relispopulated FROM pg_class WHERE oid = 'tm'::regclass;
|
||||||
|
@ -59,8 +60,9 @@ EXPLAIN (costs off)
|
||||||
Sort
|
Sort
|
||||||
Sort Key: t.type
|
Sort Key: t.type
|
||||||
-> HashAggregate
|
-> HashAggregate
|
||||||
|
Group Key: t.type
|
||||||
-> Seq Scan on t
|
-> Seq Scan on t
|
||||||
(4 rows)
|
(5 rows)
|
||||||
|
|
||||||
CREATE MATERIALIZED VIEW tvm AS SELECT * FROM tv ORDER BY type;
|
CREATE MATERIALIZED VIEW tvm AS SELECT * FROM tv ORDER BY type;
|
||||||
SELECT * FROM tvm;
|
SELECT * FROM tvm;
|
||||||
|
@ -82,8 +84,9 @@ EXPLAIN (costs off)
|
||||||
---------------------------
|
---------------------------
|
||||||
Aggregate
|
Aggregate
|
||||||
-> HashAggregate
|
-> HashAggregate
|
||||||
|
Group Key: t.type
|
||||||
-> Seq Scan on t
|
-> Seq Scan on t
|
||||||
(3 rows)
|
(4 rows)
|
||||||
|
|
||||||
CREATE MATERIALIZED VIEW tvvm AS SELECT * FROM tvv;
|
CREATE MATERIALIZED VIEW tvvm AS SELECT * FROM tvv;
|
||||||
CREATE VIEW tvvmv AS SELECT * FROM tvvm;
|
CREATE VIEW tvvmv AS SELECT * FROM tvvm;
|
||||||
|
|
|
@ -494,12 +494,13 @@ explain (costs off)
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
---------------------------------------------------
|
---------------------------------------------------
|
||||||
HashAggregate
|
HashAggregate
|
||||||
|
Group Key: ((t1.a || t1.b))
|
||||||
-> Append
|
-> Append
|
||||||
-> Index Scan using t1_ab_idx on t1
|
-> Index Scan using t1_ab_idx on t1
|
||||||
Index Cond: ((a || b) = 'ab'::text)
|
Index Cond: ((a || b) = 'ab'::text)
|
||||||
-> Index Only Scan using t2_pkey on t2
|
-> Index Only Scan using t2_pkey on t2
|
||||||
Index Cond: (ab = 'ab'::text)
|
Index Cond: (ab = 'ab'::text)
|
||||||
(6 rows)
|
(7 rows)
|
||||||
|
|
||||||
reset enable_seqscan;
|
reset enable_seqscan;
|
||||||
reset enable_indexscan;
|
reset enable_indexscan;
|
||||||
|
@ -552,17 +553,18 @@ SELECT * FROM
|
||||||
SELECT 2 AS t, 4 AS x) ss
|
SELECT 2 AS t, 4 AS x) ss
|
||||||
WHERE x < 4
|
WHERE x < 4
|
||||||
ORDER BY x;
|
ORDER BY x;
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
--------------------------------
|
--------------------------------------------------------
|
||||||
Sort
|
Sort
|
||||||
Sort Key: ss.x
|
Sort Key: ss.x
|
||||||
-> Subquery Scan on ss
|
-> Subquery Scan on ss
|
||||||
Filter: (ss.x < 4)
|
Filter: (ss.x < 4)
|
||||||
-> HashAggregate
|
-> HashAggregate
|
||||||
|
Group Key: (1), (generate_series(1, 10))
|
||||||
-> Append
|
-> Append
|
||||||
-> Result
|
-> Result
|
||||||
-> Result
|
-> Result
|
||||||
(8 rows)
|
(9 rows)
|
||||||
|
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
(SELECT 1 AS t, generate_series(1,10) AS x
|
(SELECT 1 AS t, generate_series(1,10) AS x
|
||||||
|
|
|
@ -619,12 +619,13 @@ explain (costs off)
|
||||||
select first_value(max(x)) over (), y
|
select first_value(max(x)) over (), y
|
||||||
from (select unique1 as x, ten+four as y from tenk1) ss
|
from (select unique1 as x, ten+four as y from tenk1) ss
|
||||||
group by y;
|
group by y;
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
-------------------------------
|
---------------------------------------------
|
||||||
WindowAgg
|
WindowAgg
|
||||||
-> HashAggregate
|
-> HashAggregate
|
||||||
|
Group Key: (tenk1.ten + tenk1.four)
|
||||||
-> Seq Scan on tenk1
|
-> Seq Scan on tenk1
|
||||||
(3 rows)
|
(4 rows)
|
||||||
|
|
||||||
-- test non-default frame specifications
|
-- test non-default frame specifications
|
||||||
SELECT four, ten,
|
SELECT four, ten,
|
||||||
|
|
Loading…
Reference in New Issue