mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Speed up planner's scanning for parallel-query hazards.
We need to scan the whole parse tree for parallel-unsafe functions. If there are none, we'll later need to determine whether particular subtrees contain any parallel-restricted functions. The previous coding retained no knowledge from the first scan, even though this is very wasteful in the common case where the query contains only parallel-safe functions. We can bypass all of the later scans by remembering that fact. This provides a small but measurable speed improvement when the case applies, and shouldn't cost anything when it doesn't. Patch by me, reviewed by Robert Haas Discussion: <3740.1471538387@sss.pgh.pa.us>
This commit is contained in:
@ -23,6 +23,7 @@
|
||||
#include "access/sysattr.h"
|
||||
#include "access/xact.h"
|
||||
#include "catalog/pg_constraint_fn.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "executor/executor.h"
|
||||
#include "executor/nodeAgg.h"
|
||||
@ -241,12 +242,26 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
|
||||
* time and execution time, so don't generate a parallel plan if we're in
|
||||
* serializable mode.
|
||||
*/
|
||||
glob->parallelModeOK = (cursorOptions & CURSOR_OPT_PARALLEL_OK) != 0 &&
|
||||
IsUnderPostmaster && dynamic_shared_memory_type != DSM_IMPL_NONE &&
|
||||
parse->commandType == CMD_SELECT && !parse->hasModifyingCTE &&
|
||||
parse->utilityStmt == NULL && max_parallel_workers_per_gather > 0 &&
|
||||
!IsParallelWorker() && !IsolationIsSerializable() &&
|
||||
!has_parallel_hazard((Node *) parse, true);
|
||||
if ((cursorOptions & CURSOR_OPT_PARALLEL_OK) != 0 &&
|
||||
IsUnderPostmaster &&
|
||||
dynamic_shared_memory_type != DSM_IMPL_NONE &&
|
||||
parse->commandType == CMD_SELECT &&
|
||||
parse->utilityStmt == NULL &&
|
||||
!parse->hasModifyingCTE &&
|
||||
max_parallel_workers_per_gather > 0 &&
|
||||
!IsParallelWorker() &&
|
||||
!IsolationIsSerializable())
|
||||
{
|
||||
/* all the cheap tests pass, so scan the query tree */
|
||||
glob->maxParallelHazard = max_parallel_hazard(parse);
|
||||
glob->parallelModeOK = (glob->maxParallelHazard != PROPARALLEL_UNSAFE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* skip the query tree scan, just assume it's unsafe */
|
||||
glob->maxParallelHazard = PROPARALLEL_UNSAFE;
|
||||
glob->parallelModeOK = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* glob->parallelModeNeeded should tell us whether it's necessary to
|
||||
@ -1802,7 +1817,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
|
||||
* computed by partial paths.
|
||||
*/
|
||||
if (current_rel->partial_pathlist &&
|
||||
!has_parallel_hazard((Node *) scanjoin_target->exprs, false))
|
||||
is_parallel_safe(root, (Node *) scanjoin_target->exprs))
|
||||
{
|
||||
/* Apply the scan/join target to each partial path */
|
||||
foreach(lc, current_rel->partial_pathlist)
|
||||
@ -1948,8 +1963,8 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
|
||||
* query.
|
||||
*/
|
||||
if (current_rel->consider_parallel &&
|
||||
!has_parallel_hazard(parse->limitOffset, false) &&
|
||||
!has_parallel_hazard(parse->limitCount, false))
|
||||
is_parallel_safe(root, parse->limitOffset) &&
|
||||
is_parallel_safe(root, parse->limitCount))
|
||||
final_rel->consider_parallel = true;
|
||||
|
||||
/*
|
||||
@ -3326,8 +3341,8 @@ create_grouping_paths(PlannerInfo *root,
|
||||
* target list and HAVING quals are parallel-safe.
|
||||
*/
|
||||
if (input_rel->consider_parallel &&
|
||||
!has_parallel_hazard((Node *) target->exprs, false) &&
|
||||
!has_parallel_hazard((Node *) parse->havingQual, false))
|
||||
is_parallel_safe(root, (Node *) target->exprs) &&
|
||||
is_parallel_safe(root, (Node *) parse->havingQual))
|
||||
grouped_rel->consider_parallel = true;
|
||||
|
||||
/*
|
||||
@ -3881,8 +3896,8 @@ create_window_paths(PlannerInfo *root,
|
||||
* target list and active windows for non-parallel-safe constructs.
|
||||
*/
|
||||
if (input_rel->consider_parallel &&
|
||||
!has_parallel_hazard((Node *) output_target->exprs, false) &&
|
||||
!has_parallel_hazard((Node *) activeWindows, false))
|
||||
is_parallel_safe(root, (Node *) output_target->exprs) &&
|
||||
is_parallel_safe(root, (Node *) activeWindows))
|
||||
window_rel->consider_parallel = true;
|
||||
|
||||
/*
|
||||
@ -4272,7 +4287,7 @@ create_ordered_paths(PlannerInfo *root,
|
||||
* target list is parallel-safe.
|
||||
*/
|
||||
if (input_rel->consider_parallel &&
|
||||
!has_parallel_hazard((Node *) target->exprs, false))
|
||||
is_parallel_safe(root, (Node *) target->exprs))
|
||||
ordered_rel->consider_parallel = true;
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user