diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 5771aabf40..11df4a04d4 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -1894,6 +1894,10 @@ ExplainNode(PlanState *planstate, List *ancestors, if (es->format == EXPLAIN_FORMAT_TEXT) appendStringInfoChar(es->str, '\n'); + if (plan->disabled_nodes != 0) + ExplainPropertyInteger("Disabled Nodes", NULL, plan->disabled_nodes, + es); + /* prepare per-worker general execution details */ if (es->workers_state && es->verbose) { diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 1960e59ef2..8e0e5977a9 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -2572,6 +2572,7 @@ create_minmaxagg_plan(PlannerInfo *root, MinMaxAggPath *best_path) 0, NULL, NULL, NULL); /* Must apply correct cost/width data to Limit node */ + plan->disabled_nodes = mminfo->path->disabled_nodes; plan->startup_cost = mminfo->path->startup_cost; plan->total_cost = mminfo->pathcost; plan->plan_rows = 1; @@ -5404,6 +5405,7 @@ order_qual_clauses(PlannerInfo *root, List *clauses) static void copy_generic_path_info(Plan *dest, Path *src) { + dest->disabled_nodes = src->disabled_nodes; dest->startup_cost = src->startup_cost; dest->total_cost = src->total_cost; dest->plan_rows = src->rows; @@ -5419,6 +5421,7 @@ copy_generic_path_info(Plan *dest, Path *src) static void copy_plan_costsize(Plan *dest, Plan *src) { + dest->disabled_nodes = src->disabled_nodes; dest->startup_cost = src->startup_cost; dest->total_cost = src->total_cost; dest->plan_rows = src->plan_rows; @@ -5452,7 +5455,7 @@ label_sort_with_costsize(PlannerInfo *root, Sort *plan, double limit_tuples) cost_sort(&sort_path, root, NIL, lefttree->total_cost, - 0, /* a Plan contains no count of disabled nodes */ + plan->plan.disabled_nodes, lefttree->plan_rows, lefttree->plan_width, 0.0, @@ -6547,11 +6550,12 @@ materialize_finished_plan(Plan *subplan) /* Set cost data */ cost_material(&matpath, - 0, /* a Plan contains no count of disabled nodes */ + subplan->disabled_nodes, subplan->startup_cost, subplan->total_cost, subplan->plan_rows, subplan->plan_width); + matplan->disabled_nodes = subplan->disabled_nodes; matplan->startup_cost = matpath.startup_cost + initplan_cost; matplan->total_cost = matpath.total_cost + initplan_cost; matplan->plan_rows = subplan->plan_rows; diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 1aeeaec95e..62cd6a6666 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -125,6 +125,7 @@ typedef struct Plan /* * estimated execution costs for plan (see costsize.c for more info) */ + int disabled_nodes; /* count of disabled nodes */ Cost startup_cost; /* cost expended before fetching any tuples */ Cost total_cost; /* total cost (assuming all tuples fetched) */ diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out index a5596ab210..8ac13b562c 100644 --- a/src/test/regress/expected/aggregates.out +++ b/src/test/regress/expected/aggregates.out @@ -2920,18 +2920,23 @@ GROUP BY c1.w, c1.z; QUERY PLAN ----------------------------------------------------- GroupAggregate + Disabled Nodes: 2 Group Key: c1.w, c1.z -> Sort + Disabled Nodes: 2 Sort Key: c1.w, c1.z, c1.x, c1.y -> Merge Join + Disabled Nodes: 2 Merge Cond: (c1.x = c2.x) -> Sort Sort Key: c1.x -> Seq Scan on group_agg_pk c1 + Disabled Nodes: 1 -> Sort Sort Key: c2.x -> Seq Scan on group_agg_pk c2 -(12 rows) + Disabled Nodes: 1 +(17 rows) SELECT avg(c1.f ORDER BY c1.x, c1.y) FROM group_agg_pk c1 JOIN group_agg_pk c2 ON c1.x = c2.x @@ -2953,19 +2958,24 @@ GROUP BY c1.y,c1.x,c2.x; QUERY PLAN ----------------------------------------------------- Group + Disabled Nodes: 2 Group Key: c1.x, c1.y -> Incremental Sort + Disabled Nodes: 2 Sort Key: c1.x, c1.y Presorted Key: c1.x -> Merge Join + Disabled Nodes: 2 Merge Cond: (c1.x = c2.x) -> Sort Sort Key: c1.x -> Seq Scan on group_agg_pk c1 + Disabled Nodes: 1 -> Sort Sort Key: c2.x -> Seq Scan on group_agg_pk c2 -(13 rows) + Disabled Nodes: 1 +(18 rows) EXPLAIN (COSTS OFF) SELECT c1.y,c1.x FROM group_agg_pk c1 @@ -2975,19 +2985,24 @@ GROUP BY c1.y,c2.x,c1.x; QUERY PLAN ----------------------------------------------------- Group + Disabled Nodes: 2 Group Key: c2.x, c1.y -> Incremental Sort + Disabled Nodes: 2 Sort Key: c2.x, c1.y Presorted Key: c2.x -> Merge Join + Disabled Nodes: 2 Merge Cond: (c1.x = c2.x) -> Sort Sort Key: c1.x -> Seq Scan on group_agg_pk c1 + Disabled Nodes: 1 -> Sort Sort Key: c2.x -> Seq Scan on group_agg_pk c2 -(13 rows) + Disabled Nodes: 1 +(18 rows) RESET enable_nestloop; RESET enable_hashjoin; diff --git a/src/test/regress/expected/btree_index.out b/src/test/regress/expected/btree_index.out index 092233cc9d..b350efe128 100644 --- a/src/test/regress/expected/btree_index.out +++ b/src/test/regress/expected/btree_index.out @@ -335,10 +335,12 @@ select proname from pg_proc where proname ilike 'ri%foo' order by 1; QUERY PLAN ---------------------------------------------- Sort + Disabled Nodes: 1 Sort Key: proname -> Seq Scan on pg_proc + Disabled Nodes: 1 Filter: (proname ~~* 'ri%foo'::text) -(4 rows) +(6 rows) reset enable_seqscan; reset enable_indexscan; diff --git a/src/test/regress/expected/collate.icu.utf8.out b/src/test/regress/expected/collate.icu.utf8.out index 7d59fb4431..31345295c1 100644 --- a/src/test/regress/expected/collate.icu.utf8.out +++ b/src/test/regress/expected/collate.icu.utf8.out @@ -989,8 +989,9 @@ select * from collate_test1 where b ilike 'abc'; QUERY PLAN ------------------------------- Seq Scan on collate_test1 + Disabled Nodes: 1 Filter: (b ~~* 'abc'::text) -(2 rows) +(3 rows) select * from collate_test1 where b ilike 'abc'; a | b @@ -1004,8 +1005,9 @@ select * from collate_test1 where b ilike 'ABC'; QUERY PLAN ------------------------------- Seq Scan on collate_test1 + Disabled Nodes: 1 Filter: (b ~~* 'ABC'::text) -(2 rows) +(3 rows) select * from collate_test1 where b ilike 'ABC'; a | b diff --git a/src/test/regress/expected/incremental_sort.out b/src/test/regress/expected/incremental_sort.out index 5fd54a10b1..79f0d37a87 100644 --- a/src/test/regress/expected/incremental_sort.out +++ b/src/test/regress/expected/incremental_sort.out @@ -701,16 +701,19 @@ explain (costs off) select * from t left join (select * from (select * from t or QUERY PLAN ------------------------------------------------ Nested Loop Left Join + Disabled Nodes: 1 Join Filter: (t_1.a = t.a) -> Seq Scan on t Filter: (a = ANY ('{1,2}'::integer[])) -> Incremental Sort + Disabled Nodes: 1 Sort Key: t_1.a, t_1.b Presorted Key: t_1.a -> Sort + Disabled Nodes: 1 Sort Key: t_1.a -> Seq Scan on t t_1 -(10 rows) +(13 rows) select * from t left join (select * from (select * from t order by a) v order by a, b) s on s.a = t.a where t.a in (1, 2); a | b | a | b diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out index ad73213414..dbb748a2d2 100644 --- a/src/test/regress/expected/inherit.out +++ b/src/test/regress/expected/inherit.out @@ -1614,6 +1614,7 @@ explain (verbose, costs off) select * from matest0 order by 1-id; QUERY PLAN ------------------------------------------------------------------------ Merge Append + Disabled Nodes: 1 Sort Key: ((1 - matest0.id)) -> Index Scan using matest0i on public.matest0 matest0_1 Output: matest0_1.id, matest0_1.name, (1 - matest0_1.id) @@ -1623,10 +1624,11 @@ explain (verbose, costs off) select * from matest0 order by 1-id; Output: matest0_3.id, matest0_3.name, ((1 - matest0_3.id)) Sort Key: ((1 - matest0_3.id)) -> Seq Scan on public.matest2 matest0_3 + Disabled Nodes: 1 Output: matest0_3.id, matest0_3.name, (1 - matest0_3.id) -> Index Scan using matest3i on public.matest3 matest0_4 Output: matest0_4.id, matest0_4.name, (1 - matest0_4.id) -(13 rows) +(15 rows) select * from matest0 order by 1-id; id | name diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out index 53f70d72ed..31fb7d142e 100644 --- a/src/test/regress/expected/join.out +++ b/src/test/regress/expected/join.out @@ -8000,13 +8000,15 @@ SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS QUERY PLAN --------------------------------------------------------- Nested Loop Anti Join + Disabled Nodes: 1 -> Seq Scan on skip_fetch t1 + Disabled Nodes: 1 -> Materialize -> Bitmap Heap Scan on skip_fetch t2 Recheck Cond: (a = 1) -> Bitmap Index Scan on skip_fetch_a_idx Index Cond: (a = 1) -(7 rows) +(9 rows) SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL; a diff --git a/src/test/regress/expected/memoize.out b/src/test/regress/expected/memoize.out index 96906104d7..df2ca5ba4e 100644 --- a/src/test/regress/expected/memoize.out +++ b/src/test/regress/expected/memoize.out @@ -333,14 +333,16 @@ SELECT * FROM strtest s1 INNER JOIN strtest s2 ON s1.n >= s2.n;', false); explain_memoize ---------------------------------------------------------------------------------- Nested Loop (actual rows=24 loops=N) + Disabled Nodes: 1 -> Seq Scan on strtest s1 (actual rows=6 loops=N) + Disabled Nodes: 1 -> Memoize (actual rows=4 loops=N) Cache Key: s1.n Cache Mode: binary Hits: 3 Misses: 3 Evictions: Zero Overflows: 0 Memory Usage: NkB -> Index Scan using strtest_n_idx on strtest s2 (actual rows=4 loops=N) Index Cond: (n <= s1.n) -(8 rows) +(10 rows) -- Ensure we get 3 hits and 3 misses SELECT explain_memoize(' @@ -348,14 +350,16 @@ SELECT * FROM strtest s1 INNER JOIN strtest s2 ON s1.t >= s2.t;', false); explain_memoize ---------------------------------------------------------------------------------- Nested Loop (actual rows=24 loops=N) + Disabled Nodes: 1 -> Seq Scan on strtest s1 (actual rows=6 loops=N) + Disabled Nodes: 1 -> Memoize (actual rows=4 loops=N) Cache Key: s1.t Cache Mode: binary Hits: 3 Misses: 3 Evictions: Zero Overflows: 0 Memory Usage: NkB -> Index Scan using strtest_t_idx on strtest s2 (actual rows=4 loops=N) Index Cond: (t <= s1.t) -(8 rows) +(10 rows) DROP TABLE strtest; -- Ensure memoize works with partitionwise join diff --git a/src/test/regress/expected/select_parallel.out b/src/test/regress/expected/select_parallel.out index bdd675319f..c565407082 100644 --- a/src/test/regress/expected/select_parallel.out +++ b/src/test/regress/expected/select_parallel.out @@ -537,10 +537,14 @@ explain (costs off) QUERY PLAN ------------------------------------------------------------ Aggregate + Disabled Nodes: 1 -> Nested Loop + Disabled Nodes: 1 -> Gather + Disabled Nodes: 1 Workers Planned: 4 -> Parallel Seq Scan on tenk2 + Disabled Nodes: 1 Filter: (thousand = 0) -> Gather Workers Planned: 4 @@ -548,7 +552,7 @@ explain (costs off) Recheck Cond: (hundred > 1) -> Bitmap Index Scan on tenk1_hundred Index Cond: (hundred > 1) -(12 rows) +(16 rows) select count(*) from tenk1, tenk2 where tenk1.hundred > 1 and tenk2.thousand=0; count diff --git a/src/test/regress/expected/union.out b/src/test/regress/expected/union.out index 0fd0e1c38b..0456d48c93 100644 --- a/src/test/regress/expected/union.out +++ b/src/test/regress/expected/union.out @@ -822,11 +822,12 @@ explain (costs off) select '123'::xid union select '123'::xid; QUERY PLAN --------------------------- HashAggregate + Disabled Nodes: 1 Group Key: ('123'::xid) -> Append -> Result -> Result -(5 rows) +(6 rows) reset enable_hashagg; --