mirror of
https://github.com/postgres/postgres.git
synced 2025-05-06 19:59:18 +03:00
Fix "force_parallel_mode = regress" to work with ANALYZE + VERBOSE.
force_parallel_mode = regress is supposed to force use of a Gather node without having any impact on EXPLAIN output. But it failed to accomplish that if both ANALYZE and VERBOSE are given, because that enables per-worker output data that you wouldn't see if the Gather hadn't been inserted. Improve the logic so that we suppress the per-worker data too. This allows putting the new test case added by commit 5935917ce back into the originally intended form (cf. 776a2c887, 22864f6e0). We can also get rid of a kluge in subselect.sql, which previously had to clean up after force_parallel_mode's failure to do what it said on the tin. Discussion: https://postgr.es/m/18445.1576177309@sss.pgh.pa.us
This commit is contained in:
parent
9067b83955
commit
b925a00f4e
@ -695,13 +695,19 @@ ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Sometimes we mark a Gather node as "invisible", which means that it's
|
* Sometimes we mark a Gather node as "invisible", which means that it's
|
||||||
* not displayed in EXPLAIN output. The purpose of this is to allow
|
* not to be displayed in EXPLAIN output. The purpose of this is to allow
|
||||||
* running regression tests with force_parallel_mode=regress to get the
|
* running regression tests with force_parallel_mode=regress to get the
|
||||||
* same results as running the same tests with force_parallel_mode=off.
|
* same results as running the same tests with force_parallel_mode=off.
|
||||||
|
* Such marking is currently only supported on a Gather at the top of the
|
||||||
|
* plan. We skip that node, and we must also hide per-worker detail data
|
||||||
|
* further down in the plan tree.
|
||||||
*/
|
*/
|
||||||
ps = queryDesc->planstate;
|
ps = queryDesc->planstate;
|
||||||
if (IsA(ps, GatherState) &&((Gather *) ps->plan)->invisible)
|
if (IsA(ps, GatherState) &&((Gather *) ps->plan)->invisible)
|
||||||
|
{
|
||||||
ps = outerPlanState(ps);
|
ps = outerPlanState(ps);
|
||||||
|
es->hide_workers = true;
|
||||||
|
}
|
||||||
ExplainNode(ps, NIL, NULL, NULL, es);
|
ExplainNode(ps, NIL, NULL, NULL, es);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -806,6 +812,10 @@ ExplainPrintJIT(ExplainState *es, int jit_flags,
|
|||||||
if (!ji || ji->created_functions == 0)
|
if (!ji || ji->created_functions == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* don't print per-worker info if we're supposed to hide that */
|
||||||
|
if (for_workers && es->hide_workers)
|
||||||
|
return;
|
||||||
|
|
||||||
/* calculate total time */
|
/* calculate total time */
|
||||||
INSTR_TIME_SET_ZERO(total_time);
|
INSTR_TIME_SET_ZERO(total_time);
|
||||||
INSTR_TIME_ADD(total_time, ji->generation_counter);
|
INSTR_TIME_ADD(total_time, ji->generation_counter);
|
||||||
@ -1877,7 +1887,8 @@ ExplainNode(PlanState *planstate, List *ancestors,
|
|||||||
show_buffer_usage(es, &planstate->instrument->bufusage);
|
show_buffer_usage(es, &planstate->instrument->bufusage);
|
||||||
|
|
||||||
/* Show worker detail */
|
/* Show worker detail */
|
||||||
if (es->analyze && es->verbose && planstate->worker_instrument)
|
if (es->analyze && es->verbose && !es->hide_workers &&
|
||||||
|
planstate->worker_instrument)
|
||||||
{
|
{
|
||||||
WorkerInstrumentation *w = planstate->worker_instrument;
|
WorkerInstrumentation *w = planstate->worker_instrument;
|
||||||
bool opened_group = false;
|
bool opened_group = false;
|
||||||
@ -2574,6 +2585,12 @@ show_sort_info(SortState *sortstate, ExplainState *es)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* You might think we should just skip this stanza entirely when
|
||||||
|
* es->hide_workers is true, but then we'd get no sort-method output at
|
||||||
|
* all. We have to make it look like worker 0's data is top-level data.
|
||||||
|
* Currently, we only bother with that for text-format output.
|
||||||
|
*/
|
||||||
if (sortstate->shared_info != NULL)
|
if (sortstate->shared_info != NULL)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
@ -2596,9 +2613,11 @@ show_sort_info(SortState *sortstate, ExplainState *es)
|
|||||||
if (es->format == EXPLAIN_FORMAT_TEXT)
|
if (es->format == EXPLAIN_FORMAT_TEXT)
|
||||||
{
|
{
|
||||||
appendStringInfoSpaces(es->str, es->indent * 2);
|
appendStringInfoSpaces(es->str, es->indent * 2);
|
||||||
|
if (n > 0 || !es->hide_workers)
|
||||||
|
appendStringInfo(es->str, "Worker %d: ", n);
|
||||||
appendStringInfo(es->str,
|
appendStringInfo(es->str,
|
||||||
"Worker %d: Sort Method: %s %s: %ldkB\n",
|
"Sort Method: %s %s: %ldkB\n",
|
||||||
n, sortMethod, spaceType, spaceUsed);
|
sortMethod, spaceType, spaceUsed);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -46,6 +46,7 @@ typedef struct ExplainState
|
|||||||
List *rtable_names; /* alias names for RTEs */
|
List *rtable_names; /* alias names for RTEs */
|
||||||
List *deparse_cxt; /* context list for deparsing expressions */
|
List *deparse_cxt; /* context list for deparsing expressions */
|
||||||
Bitmapset *printed_subplans; /* ids of SubPlans we've printed */
|
Bitmapset *printed_subplans; /* ids of SubPlans we've printed */
|
||||||
|
bool hide_workers; /* set if we find an invisible Gather */
|
||||||
} ExplainState;
|
} ExplainState;
|
||||||
|
|
||||||
/* Hook for plugins to get control in ExplainOneQuery() */
|
/* Hook for plugins to get control in ExplainOneQuery() */
|
||||||
|
@ -3163,12 +3163,12 @@ execute mt_q1(35);
|
|||||||
deallocate mt_q1;
|
deallocate mt_q1;
|
||||||
prepare mt_q2 (int) as select * from ma_test where a >= $1 order by b limit 1;
|
prepare mt_q2 (int) as select * from ma_test where a >= $1 order by b limit 1;
|
||||||
-- Ensure output list looks sane when the MergeAppend has no subplans.
|
-- Ensure output list looks sane when the MergeAppend has no subplans.
|
||||||
explain (verbose, costs off) execute mt_q2 (35);
|
explain (analyze, verbose, costs off, summary off, timing off) execute mt_q2 (35);
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
--------------------------------
|
--------------------------------------------
|
||||||
Limit
|
Limit (actual rows=0 loops=1)
|
||||||
Output: ma_test.a, ma_test.b
|
Output: ma_test.a, ma_test.b
|
||||||
-> Merge Append
|
-> Merge Append (actual rows=0 loops=1)
|
||||||
Sort Key: ma_test.b
|
Sort Key: ma_test.b
|
||||||
Subplans Removed: 3
|
Subplans Removed: 3
|
||||||
(5 rows)
|
(5 rows)
|
||||||
|
@ -1166,8 +1166,6 @@ begin
|
|||||||
select * from (select pk,c2 from sq_limit order by c1,pk) as x limit 3
|
select * from (select pk,c2 from sq_limit order by c1,pk) as x limit 3
|
||||||
loop
|
loop
|
||||||
ln := regexp_replace(ln, 'Memory: \S*', 'Memory: xxx');
|
ln := regexp_replace(ln, 'Memory: \S*', 'Memory: xxx');
|
||||||
-- this case might occur if force_parallel_mode is on:
|
|
||||||
ln := regexp_replace(ln, 'Worker 0: Sort Method', 'Sort Method');
|
|
||||||
return next ln;
|
return next ln;
|
||||||
end loop;
|
end loop;
|
||||||
end;
|
end;
|
||||||
|
@ -841,7 +841,7 @@ deallocate mt_q1;
|
|||||||
prepare mt_q2 (int) as select * from ma_test where a >= $1 order by b limit 1;
|
prepare mt_q2 (int) as select * from ma_test where a >= $1 order by b limit 1;
|
||||||
|
|
||||||
-- Ensure output list looks sane when the MergeAppend has no subplans.
|
-- Ensure output list looks sane when the MergeAppend has no subplans.
|
||||||
explain (verbose, costs off) execute mt_q2 (35);
|
explain (analyze, verbose, costs off, summary off, timing off) execute mt_q2 (35);
|
||||||
|
|
||||||
deallocate mt_q2;
|
deallocate mt_q2;
|
||||||
|
|
||||||
|
@ -631,8 +631,6 @@ begin
|
|||||||
select * from (select pk,c2 from sq_limit order by c1,pk) as x limit 3
|
select * from (select pk,c2 from sq_limit order by c1,pk) as x limit 3
|
||||||
loop
|
loop
|
||||||
ln := regexp_replace(ln, 'Memory: \S*', 'Memory: xxx');
|
ln := regexp_replace(ln, 'Memory: \S*', 'Memory: xxx');
|
||||||
-- this case might occur if force_parallel_mode is on:
|
|
||||||
ln := regexp_replace(ln, 'Worker 0: Sort Method', 'Sort Method');
|
|
||||||
return next ln;
|
return next ln;
|
||||||
end loop;
|
end loop;
|
||||||
end;
|
end;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user