0001-Teach-create_projection_plan-to-omit-projection-wher.patch
application/octet-stream
Filename: 0001-Teach-create_projection_plan-to-omit-projection-wher.patch
Type: application/octet-stream
Part: 3
Patch
Format: format-patch
Series: patch 0001
Subject: Teach create_projection_plan to omit projection where possible.
| File | + | − |
|---|---|---|
| src/backend/optimizer/plan/createplan.c | 22 | 4 |
From c9e1e168e2baeeb7203b549c25fb4b7ce305092b Mon Sep 17 00:00:00 2001
From: Robert Haas <rhaas@postgresql.org>
Date: Mon, 12 Mar 2018 12:36:57 -0400
Subject: [PATCH 1/4] Teach create_projection_plan to omit projection where
possible.
We sometimes insert a ProjectionPath into a plan tree when it isn't
actually needed. The existing code already provides for the case
where the ProjectionPath's subpath can perform the projection itself
instead of needing a Result node to do it, but previously it didn't
consider the possibility that the parent node might not actually
require the projection. This optimization also allows the "physical
tlist" optimization to be preserved in some cases where it would not
otherwise happen.
Patch by me, reviewed by Amit Kapila.
---
src/backend/optimizer/plan/createplan.c | 26 ++++++++++++++++++++++----
1 file changed, 22 insertions(+), 4 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 8b4f031d96..997d032939 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -87,7 +87,9 @@ static Material *create_material_plan(PlannerInfo *root, MaterialPath *best_path
static Plan *create_unique_plan(PlannerInfo *root, UniquePath *best_path,
int flags);
static Gather *create_gather_plan(PlannerInfo *root, GatherPath *best_path);
-static Plan *create_projection_plan(PlannerInfo *root, ProjectionPath *best_path);
+static Plan *create_projection_plan(PlannerInfo *root,
+ ProjectionPath *best_path,
+ int flags);
static Plan *inject_projection_plan(Plan *subplan, List *tlist, bool parallel_safe);
static Sort *create_sort_plan(PlannerInfo *root, SortPath *best_path, int flags);
static Group *create_group_plan(PlannerInfo *root, GroupPath *best_path);
@@ -400,7 +402,8 @@ create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
if (IsA(best_path, ProjectionPath))
{
plan = create_projection_plan(root,
- (ProjectionPath *) best_path);
+ (ProjectionPath *) best_path,
+ flags);
}
else if (IsA(best_path, MinMaxAggPath))
{
@@ -1567,7 +1570,7 @@ create_gather_merge_plan(PlannerInfo *root, GatherMergePath *best_path)
* but sometimes we can just let the subplan do the work.
*/
static Plan *
-create_projection_plan(PlannerInfo *root, ProjectionPath *best_path)
+create_projection_plan(PlannerInfo *root, ProjectionPath *best_path, int flags)
{
Plan *plan;
Plan *subplan;
@@ -1576,7 +1579,22 @@ create_projection_plan(PlannerInfo *root, ProjectionPath *best_path)
/* Since we intend to project, we don't need to constrain child tlist */
subplan = create_plan_recurse(root, best_path->subpath, 0);
- tlist = build_path_tlist(root, &best_path->path);
+ /*
+ * If our caller doesn't really care what tlist we return, then we might
+ * not really need to project. If use_physical_tlist returns false, then
+ * we're obliged to project. If it returns true, we can skip actually
+ * projecting but must still correctly label the input path's tlist with
+ * the sortgroupref information if the caller has so requested.
+ */
+ if (!use_physical_tlist(root, &best_path->path, flags))
+ tlist = build_path_tlist(root, &best_path->path);
+ else if ((flags & CP_LABEL_TLIST) != 0)
+ {
+ tlist = copyObject(subplan->targetlist);
+ apply_pathtarget_labeling_to_tlist(tlist, best_path->path.pathtarget);
+ }
+ else
+ return subplan;
/*
* We might not really need a Result node here, either because the subplan
--
2.14.3 (Apple Git-98)