mirror of
https://github.com/postgres/postgres.git
synced 2025-05-08 07:21:33 +03:00
Adjust EXPLAIN's output for disabled nodes
c01743aa4 added EXPLAIN output to display the plan node's disabled_node count whenever that count is above 0. Seemingly, there weren't many people who liked that output as each parent of a disabled node would also have a "Disabled Nodes" output due to the way disabled_nodes is accumulated towards the root plan node. It was often hard and sometimes impossible to figure out which nodes were disabled from looking at EXPLAIN. You might think it would be possible to manually add up the numbers from the "Disabled Nodes" output of a given node's children to figure out if that node has a higher disabled_nodes count than its children, but that wouldn't have worked for Append and Merge Append nodes if some disabled child nodes were run-time pruned during init plan. Those children are not displayed in EXPLAIN. Here we attempt to improve this output by only showing "Disabled: true" against only the nodes which are explicitly disabled themselves. That seems to be the output that's desired by the most people who voiced their opinion. This is done by summing up the disabled_nodes of the given node's children and checking if that number is less than the disabled_nodes of the current node. This commit also fixes a bug in make_sort() which was neglecting to set the Sort's disabled_nodes field. This should have copied what was done in cost_sort(), but it hadn't been updated. With the new output, the choice to not maintain that field properly was clearly wrong as the disabled-ness of the node was attributed to the Sort's parent instead. Reviewed-by: Laurenz Albe, Alena Rybakina Discussion: https://postgr.es/m/9e4ad616bebb103ec2084bf6f724cfc739e7fabb.camel@cybertec.at
This commit is contained in:
parent
c75c6f8d28
commit
161320b4b9
@ -1363,6 +1363,96 @@ ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
|
|||||||
return planstate_tree_walker(planstate, ExplainPreScanNode, rels_used);
|
return planstate_tree_walker(planstate, ExplainPreScanNode, rels_used);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* plan_is_disabled
|
||||||
|
* Checks if the given plan node type was disabled during query planning.
|
||||||
|
* This is evident by the disable_node field being higher than the sum of
|
||||||
|
* the disabled_node field from the plan's children.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
plan_is_disabled(Plan *plan)
|
||||||
|
{
|
||||||
|
int child_disabled_nodes;
|
||||||
|
|
||||||
|
/* The node is certainly not disabled if this is zero */
|
||||||
|
if (plan->disabled_nodes == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
child_disabled_nodes = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle special nodes first. Children of BitmapOrs and BitmapAnds can't
|
||||||
|
* be disabled, so no need to handle those specifically.
|
||||||
|
*/
|
||||||
|
if (IsA(plan, Append))
|
||||||
|
{
|
||||||
|
ListCell *lc;
|
||||||
|
Append *aplan = (Append *) plan;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sum the Append childrens' disabled_nodes. This purposefully
|
||||||
|
* includes any run-time pruned children. Ignoring those could give
|
||||||
|
* us the incorrect number of disabled nodes.
|
||||||
|
*/
|
||||||
|
foreach(lc, aplan->appendplans)
|
||||||
|
{
|
||||||
|
Plan *subplan = lfirst(lc);
|
||||||
|
|
||||||
|
child_disabled_nodes += subplan->disabled_nodes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (IsA(plan, MergeAppend))
|
||||||
|
{
|
||||||
|
ListCell *lc;
|
||||||
|
MergeAppend *maplan = (MergeAppend *) plan;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sum the MergeAppend childrens' disabled_nodes. This purposefully
|
||||||
|
* includes any run-time pruned children. Ignoring those could give
|
||||||
|
* us the incorrect number of disabled nodes.
|
||||||
|
*/
|
||||||
|
foreach(lc, maplan->mergeplans)
|
||||||
|
{
|
||||||
|
Plan *subplan = lfirst(lc);
|
||||||
|
|
||||||
|
child_disabled_nodes += subplan->disabled_nodes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (IsA(plan, SubqueryScan))
|
||||||
|
child_disabled_nodes += ((SubqueryScan *) plan)->subplan->disabled_nodes;
|
||||||
|
else if (IsA(plan, CustomScan))
|
||||||
|
{
|
||||||
|
ListCell *lc;
|
||||||
|
CustomScan *cplan = (CustomScan *) plan;
|
||||||
|
|
||||||
|
foreach(lc, cplan->custom_plans)
|
||||||
|
{
|
||||||
|
Plan *subplan = lfirst(lc);
|
||||||
|
|
||||||
|
child_disabled_nodes += subplan->disabled_nodes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Else, sum up disabled_nodes from the plan's inner and outer side.
|
||||||
|
*/
|
||||||
|
if (outerPlan(plan))
|
||||||
|
child_disabled_nodes += outerPlan(plan)->disabled_nodes;
|
||||||
|
if (innerPlan(plan))
|
||||||
|
child_disabled_nodes += innerPlan(plan)->disabled_nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It's disabled if the plan's disable_nodes is higher than the sum of its
|
||||||
|
* child's plan disabled_nodes.
|
||||||
|
*/
|
||||||
|
if (plan->disabled_nodes > child_disabled_nodes)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ExplainNode -
|
* ExplainNode -
|
||||||
* Appends a description of a plan tree to es->str
|
* Appends a description of a plan tree to es->str
|
||||||
@ -1399,6 +1489,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
|
|||||||
ExplainWorkersState *save_workers_state = es->workers_state;
|
ExplainWorkersState *save_workers_state = es->workers_state;
|
||||||
int save_indent = es->indent;
|
int save_indent = es->indent;
|
||||||
bool haschildren;
|
bool haschildren;
|
||||||
|
bool isdisabled;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prepare per-worker output buffers, if needed. We'll append the data in
|
* Prepare per-worker output buffers, if needed. We'll append the data in
|
||||||
@ -1914,9 +2005,10 @@ ExplainNode(PlanState *planstate, List *ancestors,
|
|||||||
if (es->format == EXPLAIN_FORMAT_TEXT)
|
if (es->format == EXPLAIN_FORMAT_TEXT)
|
||||||
appendStringInfoChar(es->str, '\n');
|
appendStringInfoChar(es->str, '\n');
|
||||||
|
|
||||||
if (plan->disabled_nodes != 0)
|
|
||||||
ExplainPropertyInteger("Disabled Nodes", NULL, plan->disabled_nodes,
|
isdisabled = plan_is_disabled(plan);
|
||||||
es);
|
if (es->format != EXPLAIN_FORMAT_TEXT || isdisabled)
|
||||||
|
ExplainPropertyBool("Disabled", isdisabled, es);
|
||||||
|
|
||||||
/* prepare per-worker general execution details */
|
/* prepare per-worker general execution details */
|
||||||
if (es->workers_state && es->verbose)
|
if (es->workers_state && es->verbose)
|
||||||
|
@ -6149,6 +6149,7 @@ make_sort(Plan *lefttree, int numCols,
|
|||||||
|
|
||||||
plan = &node->plan;
|
plan = &node->plan;
|
||||||
plan->targetlist = lefttree->targetlist;
|
plan->targetlist = lefttree->targetlist;
|
||||||
|
plan->disabled_nodes = lefttree->disabled_nodes + (enable_sort == false);
|
||||||
plan->qual = NIL;
|
plan->qual = NIL;
|
||||||
plan->lefttree = lefttree;
|
plan->lefttree = lefttree;
|
||||||
plan->righttree = NULL;
|
plan->righttree = NULL;
|
||||||
|
@ -2944,23 +2944,20 @@ GROUP BY c1.w, c1.z;
|
|||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
-----------------------------------------------------
|
-----------------------------------------------------
|
||||||
GroupAggregate
|
GroupAggregate
|
||||||
Disabled Nodes: 2
|
|
||||||
Group Key: c1.w, c1.z
|
Group Key: c1.w, c1.z
|
||||||
-> Sort
|
-> Sort
|
||||||
Disabled Nodes: 2
|
|
||||||
Sort Key: c1.w, c1.z, c1.x, c1.y
|
Sort Key: c1.w, c1.z, c1.x, c1.y
|
||||||
-> Merge Join
|
-> Merge Join
|
||||||
Disabled Nodes: 2
|
|
||||||
Merge Cond: (c1.x = c2.x)
|
Merge Cond: (c1.x = c2.x)
|
||||||
-> Sort
|
-> Sort
|
||||||
Sort Key: c1.x
|
Sort Key: c1.x
|
||||||
-> Seq Scan on group_agg_pk c1
|
-> Seq Scan on group_agg_pk c1
|
||||||
Disabled Nodes: 1
|
Disabled: true
|
||||||
-> Sort
|
-> Sort
|
||||||
Sort Key: c2.x
|
Sort Key: c2.x
|
||||||
-> Seq Scan on group_agg_pk c2
|
-> Seq Scan on group_agg_pk c2
|
||||||
Disabled Nodes: 1
|
Disabled: true
|
||||||
(17 rows)
|
(14 rows)
|
||||||
|
|
||||||
SELECT avg(c1.f ORDER BY c1.x, c1.y)
|
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
|
FROM group_agg_pk c1 JOIN group_agg_pk c2 ON c1.x = c2.x
|
||||||
@ -2982,24 +2979,21 @@ GROUP BY c1.y,c1.x,c2.x;
|
|||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
-----------------------------------------------------
|
-----------------------------------------------------
|
||||||
Group
|
Group
|
||||||
Disabled Nodes: 2
|
|
||||||
Group Key: c1.x, c1.y
|
Group Key: c1.x, c1.y
|
||||||
-> Incremental Sort
|
-> Incremental Sort
|
||||||
Disabled Nodes: 2
|
|
||||||
Sort Key: c1.x, c1.y
|
Sort Key: c1.x, c1.y
|
||||||
Presorted Key: c1.x
|
Presorted Key: c1.x
|
||||||
-> Merge Join
|
-> Merge Join
|
||||||
Disabled Nodes: 2
|
|
||||||
Merge Cond: (c1.x = c2.x)
|
Merge Cond: (c1.x = c2.x)
|
||||||
-> Sort
|
-> Sort
|
||||||
Sort Key: c1.x
|
Sort Key: c1.x
|
||||||
-> Seq Scan on group_agg_pk c1
|
-> Seq Scan on group_agg_pk c1
|
||||||
Disabled Nodes: 1
|
Disabled: true
|
||||||
-> Sort
|
-> Sort
|
||||||
Sort Key: c2.x
|
Sort Key: c2.x
|
||||||
-> Seq Scan on group_agg_pk c2
|
-> Seq Scan on group_agg_pk c2
|
||||||
Disabled Nodes: 1
|
Disabled: true
|
||||||
(18 rows)
|
(15 rows)
|
||||||
|
|
||||||
EXPLAIN (COSTS OFF)
|
EXPLAIN (COSTS OFF)
|
||||||
SELECT c1.y,c1.x FROM group_agg_pk c1
|
SELECT c1.y,c1.x FROM group_agg_pk c1
|
||||||
@ -3009,24 +3003,21 @@ GROUP BY c1.y,c2.x,c1.x;
|
|||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
-----------------------------------------------------
|
-----------------------------------------------------
|
||||||
Group
|
Group
|
||||||
Disabled Nodes: 2
|
|
||||||
Group Key: c2.x, c1.y
|
Group Key: c2.x, c1.y
|
||||||
-> Incremental Sort
|
-> Incremental Sort
|
||||||
Disabled Nodes: 2
|
|
||||||
Sort Key: c2.x, c1.y
|
Sort Key: c2.x, c1.y
|
||||||
Presorted Key: c2.x
|
Presorted Key: c2.x
|
||||||
-> Merge Join
|
-> Merge Join
|
||||||
Disabled Nodes: 2
|
|
||||||
Merge Cond: (c1.x = c2.x)
|
Merge Cond: (c1.x = c2.x)
|
||||||
-> Sort
|
-> Sort
|
||||||
Sort Key: c1.x
|
Sort Key: c1.x
|
||||||
-> Seq Scan on group_agg_pk c1
|
-> Seq Scan on group_agg_pk c1
|
||||||
Disabled Nodes: 1
|
Disabled: true
|
||||||
-> Sort
|
-> Sort
|
||||||
Sort Key: c2.x
|
Sort Key: c2.x
|
||||||
-> Seq Scan on group_agg_pk c2
|
-> Seq Scan on group_agg_pk c2
|
||||||
Disabled Nodes: 1
|
Disabled: true
|
||||||
(18 rows)
|
(15 rows)
|
||||||
|
|
||||||
RESET enable_nestloop;
|
RESET enable_nestloop;
|
||||||
RESET enable_hashjoin;
|
RESET enable_hashjoin;
|
||||||
|
@ -335,12 +335,11 @@ select proname from pg_proc where proname ilike 'ri%foo' order by 1;
|
|||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
Sort
|
Sort
|
||||||
Disabled Nodes: 1
|
|
||||||
Sort Key: proname
|
Sort Key: proname
|
||||||
-> Seq Scan on pg_proc
|
-> Seq Scan on pg_proc
|
||||||
Disabled Nodes: 1
|
Disabled: true
|
||||||
Filter: (proname ~~* 'ri%foo'::text)
|
Filter: (proname ~~* 'ri%foo'::text)
|
||||||
(6 rows)
|
(5 rows)
|
||||||
|
|
||||||
reset enable_seqscan;
|
reset enable_seqscan;
|
||||||
reset enable_indexscan;
|
reset enable_indexscan;
|
||||||
|
@ -989,7 +989,7 @@ select * from collate_test1 where b ilike 'abc';
|
|||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
-------------------------------
|
-------------------------------
|
||||||
Seq Scan on collate_test1
|
Seq Scan on collate_test1
|
||||||
Disabled Nodes: 1
|
Disabled: true
|
||||||
Filter: (b ~~* 'abc'::text)
|
Filter: (b ~~* 'abc'::text)
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
@ -1005,7 +1005,7 @@ select * from collate_test1 where b ilike 'ABC';
|
|||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
-------------------------------
|
-------------------------------
|
||||||
Seq Scan on collate_test1
|
Seq Scan on collate_test1
|
||||||
Disabled Nodes: 1
|
Disabled: true
|
||||||
Filter: (b ~~* 'ABC'::text)
|
Filter: (b ~~* 'ABC'::text)
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
|
@ -104,6 +104,7 @@ select explain_filter('explain (analyze, buffers, format xml) select * from int8
|
|||||||
<Actual-Total-Time>N.N</Actual-Total-Time> +
|
<Actual-Total-Time>N.N</Actual-Total-Time> +
|
||||||
<Actual-Rows>N</Actual-Rows> +
|
<Actual-Rows>N</Actual-Rows> +
|
||||||
<Actual-Loops>N</Actual-Loops> +
|
<Actual-Loops>N</Actual-Loops> +
|
||||||
|
<Disabled>false</Disabled> +
|
||||||
<Shared-Hit-Blocks>N</Shared-Hit-Blocks> +
|
<Shared-Hit-Blocks>N</Shared-Hit-Blocks> +
|
||||||
<Shared-Read-Blocks>N</Shared-Read-Blocks> +
|
<Shared-Read-Blocks>N</Shared-Read-Blocks> +
|
||||||
<Shared-Dirtied-Blocks>N</Shared-Dirtied-Blocks>+
|
<Shared-Dirtied-Blocks>N</Shared-Dirtied-Blocks>+
|
||||||
@ -152,6 +153,7 @@ select explain_filter('explain (analyze, serialize, buffers, format yaml) select
|
|||||||
Actual Total Time: N.N +
|
Actual Total Time: N.N +
|
||||||
Actual Rows: N +
|
Actual Rows: N +
|
||||||
Actual Loops: N +
|
Actual Loops: N +
|
||||||
|
Disabled: false +
|
||||||
Shared Hit Blocks: N +
|
Shared Hit Blocks: N +
|
||||||
Shared Read Blocks: N +
|
Shared Read Blocks: N +
|
||||||
Shared Dirtied Blocks: N +
|
Shared Dirtied Blocks: N +
|
||||||
@ -213,6 +215,7 @@ select explain_filter('explain (buffers, format json) select * from int8_tbl i8'
|
|||||||
"Total Cost": N.N, +
|
"Total Cost": N.N, +
|
||||||
"Plan Rows": N, +
|
"Plan Rows": N, +
|
||||||
"Plan Width": N, +
|
"Plan Width": N, +
|
||||||
|
"Disabled": false, +
|
||||||
"Shared Hit Blocks": N, +
|
"Shared Hit Blocks": N, +
|
||||||
"Shared Read Blocks": N, +
|
"Shared Read Blocks": N, +
|
||||||
"Shared Dirtied Blocks": N, +
|
"Shared Dirtied Blocks": N, +
|
||||||
@ -262,6 +265,7 @@ select explain_filter('explain (analyze, buffers, format json) select * from int
|
|||||||
"Actual Total Time": N.N, +
|
"Actual Total Time": N.N, +
|
||||||
"Actual Rows": N, +
|
"Actual Rows": N, +
|
||||||
"Actual Loops": N, +
|
"Actual Loops": N, +
|
||||||
|
"Disabled": false, +
|
||||||
"Shared Hit Blocks": N, +
|
"Shared Hit Blocks": N, +
|
||||||
"Shared Read Blocks": N, +
|
"Shared Read Blocks": N, +
|
||||||
"Shared Dirtied Blocks": N, +
|
"Shared Dirtied Blocks": N, +
|
||||||
@ -370,6 +374,7 @@ select explain_filter('explain (memory, summary, format yaml) select * from int8
|
|||||||
Total Cost: N.N +
|
Total Cost: N.N +
|
||||||
Plan Rows: N +
|
Plan Rows: N +
|
||||||
Plan Width: N +
|
Plan Width: N +
|
||||||
|
Disabled: false +
|
||||||
Planning: +
|
Planning: +
|
||||||
Memory Used: N +
|
Memory Used: N +
|
||||||
Memory Allocated: N +
|
Memory Allocated: N +
|
||||||
@ -394,7 +399,8 @@ select explain_filter('explain (memory, analyze, format json) select * from int8
|
|||||||
"Actual Startup Time": N.N, +
|
"Actual Startup Time": N.N, +
|
||||||
"Actual Total Time": N.N, +
|
"Actual Total Time": N.N, +
|
||||||
"Actual Rows": N, +
|
"Actual Rows": N, +
|
||||||
"Actual Loops": N +
|
"Actual Loops": N, +
|
||||||
|
"Disabled": false +
|
||||||
}, +
|
}, +
|
||||||
"Planning": { +
|
"Planning": { +
|
||||||
"Memory Used": N, +
|
"Memory Used": N, +
|
||||||
@ -497,6 +503,7 @@ select jsonb_pretty(
|
|||||||
"string4" +
|
"string4" +
|
||||||
], +
|
], +
|
||||||
"Schema": "public", +
|
"Schema": "public", +
|
||||||
|
"Disabled": false, +
|
||||||
"Node Type": "Seq Scan", +
|
"Node Type": "Seq Scan", +
|
||||||
"Plan Rows": 0, +
|
"Plan Rows": 0, +
|
||||||
"Plan Width": 0, +
|
"Plan Width": 0, +
|
||||||
@ -540,6 +547,7 @@ select jsonb_pretty(
|
|||||||
"stringu2", +
|
"stringu2", +
|
||||||
"string4" +
|
"string4" +
|
||||||
], +
|
], +
|
||||||
|
"Disabled": false, +
|
||||||
"Sort Key": [ +
|
"Sort Key": [ +
|
||||||
"tenk1.tenthous" +
|
"tenk1.tenthous" +
|
||||||
], +
|
], +
|
||||||
@ -586,6 +594,7 @@ select jsonb_pretty(
|
|||||||
"stringu2", +
|
"stringu2", +
|
||||||
"string4" +
|
"string4" +
|
||||||
], +
|
], +
|
||||||
|
"Disabled": false, +
|
||||||
"Node Type": "Gather Merge", +
|
"Node Type": "Gather Merge", +
|
||||||
"Plan Rows": 0, +
|
"Plan Rows": 0, +
|
||||||
"Plan Width": 0, +
|
"Plan Width": 0, +
|
||||||
|
@ -538,6 +538,7 @@ select jsonb_pretty(explain_analyze_inc_sort_nodes_without_memory('select * from
|
|||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
[ +
|
[ +
|
||||||
{ +
|
{ +
|
||||||
|
"Disabled": false, +
|
||||||
"Sort Key": [ +
|
"Sort Key": [ +
|
||||||
"t.a", +
|
"t.a", +
|
||||||
"t.b" +
|
"t.b" +
|
||||||
@ -701,19 +702,17 @@ explain (costs off) select * from t left join (select * from (select * from t or
|
|||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
Nested Loop Left Join
|
Nested Loop Left Join
|
||||||
Disabled Nodes: 1
|
|
||||||
Join Filter: (t_1.a = t.a)
|
Join Filter: (t_1.a = t.a)
|
||||||
-> Seq Scan on t
|
-> Seq Scan on t
|
||||||
Filter: (a = ANY ('{1,2}'::integer[]))
|
Filter: (a = ANY ('{1,2}'::integer[]))
|
||||||
-> Incremental Sort
|
-> Incremental Sort
|
||||||
Disabled Nodes: 1
|
|
||||||
Sort Key: t_1.a, t_1.b
|
Sort Key: t_1.a, t_1.b
|
||||||
Presorted Key: t_1.a
|
Presorted Key: t_1.a
|
||||||
-> Sort
|
-> Sort
|
||||||
Disabled Nodes: 1
|
Disabled: true
|
||||||
Sort Key: t_1.a
|
Sort Key: t_1.a
|
||||||
-> Seq Scan on t t_1
|
-> Seq Scan on t t_1
|
||||||
(13 rows)
|
(11 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);
|
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
|
a | b | a | b
|
||||||
@ -744,6 +743,7 @@ select jsonb_pretty(explain_analyze_inc_sort_nodes_without_memory('select * from
|
|||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
[ +
|
[ +
|
||||||
{ +
|
{ +
|
||||||
|
"Disabled": false, +
|
||||||
"Sort Key": [ +
|
"Sort Key": [ +
|
||||||
"t.a", +
|
"t.a", +
|
||||||
"t.b" +
|
"t.b" +
|
||||||
|
@ -1614,7 +1614,6 @@ explain (verbose, costs off) select * from matest0 order by 1-id;
|
|||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
Merge Append
|
Merge Append
|
||||||
Disabled Nodes: 1
|
|
||||||
Sort Key: ((1 - matest0.id))
|
Sort Key: ((1 - matest0.id))
|
||||||
-> Index Scan using matest0i on public.matest0 matest0_1
|
-> Index Scan using matest0i on public.matest0 matest0_1
|
||||||
Output: matest0_1.id, matest0_1.name, (1 - matest0_1.id)
|
Output: matest0_1.id, matest0_1.name, (1 - matest0_1.id)
|
||||||
@ -1624,11 +1623,11 @@ explain (verbose, costs off) select * from matest0 order by 1-id;
|
|||||||
Output: matest0_3.id, matest0_3.name, ((1 - matest0_3.id))
|
Output: matest0_3.id, matest0_3.name, ((1 - matest0_3.id))
|
||||||
Sort Key: ((1 - matest0_3.id))
|
Sort Key: ((1 - matest0_3.id))
|
||||||
-> Seq Scan on public.matest2 matest0_3
|
-> Seq Scan on public.matest2 matest0_3
|
||||||
Disabled Nodes: 1
|
Disabled: true
|
||||||
Output: matest0_3.id, matest0_3.name, (1 - matest0_3.id)
|
Output: matest0_3.id, matest0_3.name, (1 - matest0_3.id)
|
||||||
-> Index Scan using matest3i on public.matest3 matest0_4
|
-> Index Scan using matest3i on public.matest3 matest0_4
|
||||||
Output: matest0_4.id, matest0_4.name, (1 - matest0_4.id)
|
Output: matest0_4.id, matest0_4.name, (1 - matest0_4.id)
|
||||||
(15 rows)
|
(14 rows)
|
||||||
|
|
||||||
select * from matest0 order by 1-id;
|
select * from matest0 order by 1-id;
|
||||||
id | name
|
id | name
|
||||||
|
@ -218,6 +218,7 @@ explain (costs off, format json) insert into insertconflicttest values (0, 'Bilb
|
|||||||
"Async Capable": false, +
|
"Async Capable": false, +
|
||||||
"Relation Name": "insertconflicttest", +
|
"Relation Name": "insertconflicttest", +
|
||||||
"Alias": "insertconflicttest", +
|
"Alias": "insertconflicttest", +
|
||||||
|
"Disabled": false, +
|
||||||
"Conflict Resolution": "UPDATE", +
|
"Conflict Resolution": "UPDATE", +
|
||||||
"Conflict Arbiter Indexes": ["key_index"], +
|
"Conflict Arbiter Indexes": ["key_index"], +
|
||||||
"Conflict Filter": "(insertconflicttest.fruit <> 'Lime'::text)",+
|
"Conflict Filter": "(insertconflicttest.fruit <> 'Lime'::text)",+
|
||||||
@ -226,7 +227,8 @@ explain (costs off, format json) insert into insertconflicttest values (0, 'Bilb
|
|||||||
"Node Type": "Result", +
|
"Node Type": "Result", +
|
||||||
"Parent Relationship": "Outer", +
|
"Parent Relationship": "Outer", +
|
||||||
"Parallel Aware": false, +
|
"Parallel Aware": false, +
|
||||||
"Async Capable": false +
|
"Async Capable": false, +
|
||||||
|
"Disabled": false +
|
||||||
} +
|
} +
|
||||||
] +
|
] +
|
||||||
} +
|
} +
|
||||||
|
@ -8010,15 +8010,14 @@ SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS
|
|||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
Nested Loop Anti Join
|
Nested Loop Anti Join
|
||||||
Disabled Nodes: 1
|
|
||||||
-> Seq Scan on skip_fetch t1
|
-> Seq Scan on skip_fetch t1
|
||||||
Disabled Nodes: 1
|
Disabled: true
|
||||||
-> Materialize
|
-> Materialize
|
||||||
-> Bitmap Heap Scan on skip_fetch t2
|
-> Bitmap Heap Scan on skip_fetch t2
|
||||||
Recheck Cond: (a = 1)
|
Recheck Cond: (a = 1)
|
||||||
-> Bitmap Index Scan on skip_fetch_a_idx
|
-> Bitmap Index Scan on skip_fetch_a_idx
|
||||||
Index Cond: (a = 1)
|
Index Cond: (a = 1)
|
||||||
(9 rows)
|
(8 rows)
|
||||||
|
|
||||||
SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
|
SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
|
||||||
a
|
a
|
||||||
|
@ -303,16 +303,15 @@ SELECT * FROM strtest s1 INNER JOIN strtest s2 ON s1.n >= s2.n;', false);
|
|||||||
explain_memoize
|
explain_memoize
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
Nested Loop (actual rows=24 loops=N)
|
Nested Loop (actual rows=24 loops=N)
|
||||||
Disabled Nodes: 1
|
|
||||||
-> Seq Scan on strtest s1 (actual rows=6 loops=N)
|
-> Seq Scan on strtest s1 (actual rows=6 loops=N)
|
||||||
Disabled Nodes: 1
|
Disabled: true
|
||||||
-> Memoize (actual rows=4 loops=N)
|
-> Memoize (actual rows=4 loops=N)
|
||||||
Cache Key: s1.n
|
Cache Key: s1.n
|
||||||
Cache Mode: binary
|
Cache Mode: binary
|
||||||
Hits: 3 Misses: 3 Evictions: Zero Overflows: 0 Memory Usage: NkB
|
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 Scan using strtest_n_idx on strtest s2 (actual rows=4 loops=N)
|
||||||
Index Cond: (n <= s1.n)
|
Index Cond: (n <= s1.n)
|
||||||
(10 rows)
|
(9 rows)
|
||||||
|
|
||||||
-- Ensure we get 3 hits and 3 misses
|
-- Ensure we get 3 hits and 3 misses
|
||||||
SELECT explain_memoize('
|
SELECT explain_memoize('
|
||||||
@ -320,16 +319,15 @@ SELECT * FROM strtest s1 INNER JOIN strtest s2 ON s1.t >= s2.t;', false);
|
|||||||
explain_memoize
|
explain_memoize
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
Nested Loop (actual rows=24 loops=N)
|
Nested Loop (actual rows=24 loops=N)
|
||||||
Disabled Nodes: 1
|
|
||||||
-> Seq Scan on strtest s1 (actual rows=6 loops=N)
|
-> Seq Scan on strtest s1 (actual rows=6 loops=N)
|
||||||
Disabled Nodes: 1
|
Disabled: true
|
||||||
-> Memoize (actual rows=4 loops=N)
|
-> Memoize (actual rows=4 loops=N)
|
||||||
Cache Key: s1.t
|
Cache Key: s1.t
|
||||||
Cache Mode: binary
|
Cache Mode: binary
|
||||||
Hits: 3 Misses: 3 Evictions: Zero Overflows: 0 Memory Usage: NkB
|
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 Scan using strtest_t_idx on strtest s2 (actual rows=4 loops=N)
|
||||||
Index Cond: (t <= s1.t)
|
Index Cond: (t <= s1.t)
|
||||||
(10 rows)
|
(9 rows)
|
||||||
|
|
||||||
DROP TABLE strtest;
|
DROP TABLE strtest;
|
||||||
-- Ensure memoize works with partitionwise join
|
-- Ensure memoize works with partitionwise join
|
||||||
|
@ -537,14 +537,11 @@ explain (costs off)
|
|||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
Aggregate
|
Aggregate
|
||||||
Disabled Nodes: 1
|
|
||||||
-> Nested Loop
|
-> Nested Loop
|
||||||
Disabled Nodes: 1
|
|
||||||
-> Gather
|
-> Gather
|
||||||
Disabled Nodes: 1
|
|
||||||
Workers Planned: 4
|
Workers Planned: 4
|
||||||
-> Parallel Seq Scan on tenk2
|
-> Parallel Seq Scan on tenk2
|
||||||
Disabled Nodes: 1
|
Disabled: true
|
||||||
Filter: (thousand = 0)
|
Filter: (thousand = 0)
|
||||||
-> Gather
|
-> Gather
|
||||||
Workers Planned: 4
|
Workers Planned: 4
|
||||||
@ -552,7 +549,7 @@ explain (costs off)
|
|||||||
Recheck Cond: (hundred > 1)
|
Recheck Cond: (hundred > 1)
|
||||||
-> Bitmap Index Scan on tenk1_hundred
|
-> Bitmap Index Scan on tenk1_hundred
|
||||||
Index Cond: (hundred > 1)
|
Index Cond: (hundred > 1)
|
||||||
(16 rows)
|
(13 rows)
|
||||||
|
|
||||||
select count(*) from tenk1, tenk2 where tenk1.hundred > 1 and tenk2.thousand=0;
|
select count(*) from tenk1, tenk2 where tenk1.hundred > 1 and tenk2.thousand=0;
|
||||||
count
|
count
|
||||||
|
@ -474,6 +474,7 @@ SELECT * FROM
|
|||||||
"Async Capable": false, +
|
"Async Capable": false, +
|
||||||
"Table Function Name": "json_table", +
|
"Table Function Name": "json_table", +
|
||||||
"Alias": "json_table_func", +
|
"Alias": "json_table_func", +
|
||||||
|
"Disabled": false, +
|
||||||
"Output": ["id", "\"int\"", "text"], +
|
"Output": ["id", "\"int\"", "text"], +
|
||||||
"Table Function Call": "JSON_TABLE('null'::jsonb, '$[*]' AS json_table_path_0 PASSING 3 AS a, '\"foo\"'::jsonb AS \"b c\" COLUMNS (id FOR ORDINALITY, \"int\" integer PATH '$', text text PATH '$'))"+
|
"Table Function Call": "JSON_TABLE('null'::jsonb, '$[*]' AS json_table_path_0 PASSING 3 AS a, '\"foo\"'::jsonb AS \"b c\" COLUMNS (id FOR ORDINALITY, \"int\" integer PATH '$', text text PATH '$'))"+
|
||||||
} +
|
} +
|
||||||
|
@ -822,7 +822,7 @@ explain (costs off) select '123'::xid union select '123'::xid;
|
|||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
---------------------------
|
---------------------------
|
||||||
HashAggregate
|
HashAggregate
|
||||||
Disabled Nodes: 1
|
Disabled: true
|
||||||
Group Key: ('123'::xid)
|
Group Key: ('123'::xid)
|
||||||
-> Append
|
-> Append
|
||||||
-> Result
|
-> Result
|
||||||
|
@ -1577,6 +1577,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU
|
|||||||
"Parallel Aware": false, +
|
"Parallel Aware": false, +
|
||||||
"Async Capable": false, +
|
"Async Capable": false, +
|
||||||
"Join Type": "Inner", +
|
"Join Type": "Inner", +
|
||||||
|
"Disabled": false, +
|
||||||
"Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], +
|
"Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], +
|
||||||
"Inner Unique": false, +
|
"Inner Unique": false, +
|
||||||
"Plans": [ +
|
"Plans": [ +
|
||||||
@ -1588,6 +1589,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU
|
|||||||
"Relation Name": "xmldata", +
|
"Relation Name": "xmldata", +
|
||||||
"Schema": "public", +
|
"Schema": "public", +
|
||||||
"Alias": "xmldata", +
|
"Alias": "xmldata", +
|
||||||
|
"Disabled": false, +
|
||||||
"Output": ["xmldata.data"] +
|
"Output": ["xmldata.data"] +
|
||||||
}, +
|
}, +
|
||||||
{ +
|
{ +
|
||||||
@ -1597,6 +1599,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU
|
|||||||
"Async Capable": false, +
|
"Async Capable": false, +
|
||||||
"Table Function Name": "xmltable", +
|
"Table Function Name": "xmltable", +
|
||||||
"Alias": "f", +
|
"Alias": "f", +
|
||||||
|
"Disabled": false, +
|
||||||
"Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], +
|
"Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], +
|
||||||
"Table Function Call": "XMLTABLE(('/ROWS/ROW[COUNTRY_NAME=\"Japan\" or COUNTRY_NAME=\"India\"]'::text) PASSING (xmldata.data) COLUMNS \"COUNTRY_NAME\" text, \"REGION_ID\" integer)",+
|
"Table Function Call": "XMLTABLE(('/ROWS/ROW[COUNTRY_NAME=\"Japan\" or COUNTRY_NAME=\"India\"]'::text) PASSING (xmldata.data) COLUMNS \"COUNTRY_NAME\" text, \"REGION_ID\" integer)",+
|
||||||
"Filter": "(f.\"COUNTRY_NAME\" = 'Japan'::text)" +
|
"Filter": "(f.\"COUNTRY_NAME\" = 'Japan'::text)" +
|
||||||
|
@ -1209,6 +1209,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU
|
|||||||
"Parallel Aware": false, +
|
"Parallel Aware": false, +
|
||||||
"Async Capable": false, +
|
"Async Capable": false, +
|
||||||
"Join Type": "Inner", +
|
"Join Type": "Inner", +
|
||||||
|
"Disabled": false, +
|
||||||
"Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], +
|
"Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], +
|
||||||
"Inner Unique": false, +
|
"Inner Unique": false, +
|
||||||
"Plans": [ +
|
"Plans": [ +
|
||||||
@ -1220,6 +1221,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU
|
|||||||
"Relation Name": "xmldata", +
|
"Relation Name": "xmldata", +
|
||||||
"Schema": "public", +
|
"Schema": "public", +
|
||||||
"Alias": "xmldata", +
|
"Alias": "xmldata", +
|
||||||
|
"Disabled": false, +
|
||||||
"Output": ["xmldata.data"] +
|
"Output": ["xmldata.data"] +
|
||||||
}, +
|
}, +
|
||||||
{ +
|
{ +
|
||||||
@ -1229,6 +1231,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU
|
|||||||
"Async Capable": false, +
|
"Async Capable": false, +
|
||||||
"Table Function Name": "xmltable", +
|
"Table Function Name": "xmltable", +
|
||||||
"Alias": "f", +
|
"Alias": "f", +
|
||||||
|
"Disabled": false, +
|
||||||
"Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], +
|
"Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], +
|
||||||
"Table Function Call": "XMLTABLE(('/ROWS/ROW[COUNTRY_NAME=\"Japan\" or COUNTRY_NAME=\"India\"]'::text) PASSING (xmldata.data) COLUMNS \"COUNTRY_NAME\" text, \"REGION_ID\" integer)",+
|
"Table Function Call": "XMLTABLE(('/ROWS/ROW[COUNTRY_NAME=\"Japan\" or COUNTRY_NAME=\"India\"]'::text) PASSING (xmldata.data) COLUMNS \"COUNTRY_NAME\" text, \"REGION_ID\" integer)",+
|
||||||
"Filter": "(f.\"COUNTRY_NAME\" = 'Japan'::text)" +
|
"Filter": "(f.\"COUNTRY_NAME\" = 'Japan'::text)" +
|
||||||
|
@ -1563,6 +1563,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU
|
|||||||
"Parallel Aware": false, +
|
"Parallel Aware": false, +
|
||||||
"Async Capable": false, +
|
"Async Capable": false, +
|
||||||
"Join Type": "Inner", +
|
"Join Type": "Inner", +
|
||||||
|
"Disabled": false, +
|
||||||
"Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], +
|
"Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], +
|
||||||
"Inner Unique": false, +
|
"Inner Unique": false, +
|
||||||
"Plans": [ +
|
"Plans": [ +
|
||||||
@ -1574,6 +1575,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU
|
|||||||
"Relation Name": "xmldata", +
|
"Relation Name": "xmldata", +
|
||||||
"Schema": "public", +
|
"Schema": "public", +
|
||||||
"Alias": "xmldata", +
|
"Alias": "xmldata", +
|
||||||
|
"Disabled": false, +
|
||||||
"Output": ["xmldata.data"] +
|
"Output": ["xmldata.data"] +
|
||||||
}, +
|
}, +
|
||||||
{ +
|
{ +
|
||||||
@ -1583,6 +1585,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU
|
|||||||
"Async Capable": false, +
|
"Async Capable": false, +
|
||||||
"Table Function Name": "xmltable", +
|
"Table Function Name": "xmltable", +
|
||||||
"Alias": "f", +
|
"Alias": "f", +
|
||||||
|
"Disabled": false, +
|
||||||
"Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], +
|
"Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], +
|
||||||
"Table Function Call": "XMLTABLE(('/ROWS/ROW[COUNTRY_NAME=\"Japan\" or COUNTRY_NAME=\"India\"]'::text) PASSING (xmldata.data) COLUMNS \"COUNTRY_NAME\" text, \"REGION_ID\" integer)",+
|
"Table Function Call": "XMLTABLE(('/ROWS/ROW[COUNTRY_NAME=\"Japan\" or COUNTRY_NAME=\"India\"]'::text) PASSING (xmldata.data) COLUMNS \"COUNTRY_NAME\" text, \"REGION_ID\" integer)",+
|
||||||
"Filter": "(f.\"COUNTRY_NAME\" = 'Japan'::text)" +
|
"Filter": "(f.\"COUNTRY_NAME\" = 'Japan'::text)" +
|
||||||
|
Loading…
x
Reference in New Issue
Block a user