diff options
author | Etsuro Fujita <efujita@postgresql.org> | 2022-04-06 15:45:00 +0900 |
---|---|---|
committer | Etsuro Fujita <efujita@postgresql.org> | 2022-04-06 15:45:00 +0900 |
commit | c2bb02bc2e858ba345b8b33f1f3a54628f719d93 (patch) | |
tree | fe742ab96982b0a74ed615d0c1e4c0982715a6e6 /src/backend/optimizer/plan/createplan.c | |
parent | 376dc437de40bd17e99a37f72f88627a16d7f200 (diff) | |
download | postgresql-c2bb02bc2e858ba345b8b33f1f3a54628f719d93.tar.gz postgresql-c2bb02bc2e858ba345b8b33f1f3a54628f719d93.zip |
Allow asynchronous execution in more cases.
In commit 27e1f1456, create_append_plan() only allowed the subplan
created from a given subpath to be executed asynchronously when it was
an async-capable ForeignPath. To extend coverage, this patch handles
cases when the given subpath includes some other Path types as well that
can be omitted in the plan processing, such as a ProjectionPath directly
atop an async-capable ForeignPath, allowing asynchronous execution in
partitioned-scan/partitioned-join queries with non-Var tlist expressions
and more UNION queries.
Andrey Lepikhov and Etsuro Fujita, reviewed by Alexander Pyhalov and
Zhihong Yu.
Discussion: https://postgr.es/m/659c37a8-3e71-0ff2-394c-f04428c76f08%40postgrespro.ru
Diffstat (limited to 'src/backend/optimizer/plan/createplan.c')
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 57 |
1 files changed, 44 insertions, 13 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 179c87c6714..51591bb8128 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -82,7 +82,7 @@ static List *get_gating_quals(PlannerInfo *root, List *quals); static Plan *create_gating_plan(PlannerInfo *root, Path *path, Plan *plan, List *gating_quals); static Plan *create_join_plan(PlannerInfo *root, JoinPath *best_path); -static bool is_async_capable_path(Path *path); +static bool mark_async_capable_plan(Plan *plan, Path *path); static Plan *create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags); static Plan *create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path, @@ -1110,14 +1110,30 @@ create_join_plan(PlannerInfo *root, JoinPath *best_path) } /* - * is_async_capable_path - * Check whether a given Path node is async-capable. + * mark_async_capable_plan + * Check whether a given Path node is async-capable, and if so, mark the + * Plan node created from it as such and return true, otherwise return + * false. */ static bool -is_async_capable_path(Path *path) +mark_async_capable_plan(Plan *plan, Path *path) { switch (nodeTag(path)) { + case T_SubqueryScanPath: + { + SubqueryScan *scan_plan = (SubqueryScan *) plan; + + /* + * If a SubqueryScan node atop of an async-capable plan node + * is deletable, consider it as async-capable. + */ + if (trivial_subqueryscan(scan_plan) && + mark_async_capable_plan(scan_plan->subplan, + ((SubqueryScanPath *) path)->subpath)) + break; + return false; + } case T_ForeignPath: { FdwRoutine *fdwroutine = path->parent->fdwroutine; @@ -1125,13 +1141,27 @@ is_async_capable_path(Path *path) Assert(fdwroutine != NULL); if (fdwroutine->IsForeignPathAsyncCapable != NULL && fdwroutine->IsForeignPathAsyncCapable((ForeignPath *) path)) - return true; + break; + return false; } - break; + case T_ProjectionPath: + + /* + * If the generated plan node doesn't include a Result node, + * consider it as async-capable if the subpath is async-capable. + */ + if (!IsA(plan, Result) && + mark_async_capable_plan(plan, + ((ProjectionPath *) path)->subpath)) + return true; + return false; default: - break; + return false; } - return false; + + plan->async_capable = true; + + return true; } /* @@ -1294,14 +1324,14 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags) } } - subplans = lappend(subplans, subplan); - - /* Check to see if subplan can be executed asynchronously */ - if (consider_async && is_async_capable_path(subpath)) + /* If needed, check to see if subplan can be executed asynchronously */ + if (consider_async && mark_async_capable_plan(subplan, subpath)) { - subplan->async_capable = true; + Assert(subplan->async_capable); ++nasyncplans; } + + subplans = lappend(subplans, subplan); } /* @@ -5598,6 +5628,7 @@ make_subqueryscan(List *qptlist, plan->righttree = NULL; node->scan.scanrelid = scanrelid; node->subplan = subplan; + node->scanstatus = SUBQUERY_SCAN_UNKNOWN; return node; } |