aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/createplan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan/createplan.c')
-rw-r--r--src/backend/optimizer/plan/createplan.c89
1 files changed, 81 insertions, 8 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index bb45ef318fb..0d195a07ffc 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -179,6 +179,8 @@ static void copy_generic_path_info(Plan *dest, Path *src);
static void copy_plan_costsize(Plan *dest, Plan *src);
static void label_sort_with_costsize(PlannerInfo *root, Sort *plan,
double limit_tuples);
+static void label_incrementalsort_with_costsize(PlannerInfo *root, IncrementalSort *plan,
+ List *pathkeys, double limit_tuples);
static SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid);
static SampleScan *make_samplescan(List *qptlist, List *qpqual, Index scanrelid,
TableSampleClause *tsc);
@@ -4523,12 +4525,51 @@ create_mergejoin_plan(PlannerInfo *root,
if (best_path->outersortkeys)
{
Relids outer_relids = outer_path->parent->relids;
- Sort *sort = make_sort_from_pathkeys(outer_plan,
+ Plan *sort_plan;
+ bool use_incremental_sort = false;
+ int presorted_keys;
+
+ /*
+ * We choose to use incremental sort if it is enabled and there are
+ * presorted keys; otherwise we use full sort.
+ */
+ if (enable_incremental_sort)
+ {
+ bool is_sorted PG_USED_FOR_ASSERTS_ONLY;
+
+ is_sorted = pathkeys_count_contained_in(best_path->outersortkeys,
+ outer_path->pathkeys,
+ &presorted_keys);
+ Assert(!is_sorted);
+
+ if (presorted_keys > 0)
+ use_incremental_sort = true;
+ }
+
+ if (!use_incremental_sort)
+ {
+ sort_plan = (Plan *)
+ make_sort_from_pathkeys(outer_plan,
+ best_path->outersortkeys,
+ outer_relids);
+
+ label_sort_with_costsize(root, (Sort *) sort_plan, -1.0);
+ }
+ else
+ {
+ sort_plan = (Plan *)
+ make_incrementalsort_from_pathkeys(outer_plan,
best_path->outersortkeys,
- outer_relids);
+ outer_relids,
+ presorted_keys);
- label_sort_with_costsize(root, sort, -1.0);
- outer_plan = (Plan *) sort;
+ label_incrementalsort_with_costsize(root,
+ (IncrementalSort *) sort_plan,
+ best_path->outersortkeys,
+ -1.0);
+ }
+
+ outer_plan = sort_plan;
outerpathkeys = best_path->outersortkeys;
}
else
@@ -4536,6 +4577,11 @@ create_mergejoin_plan(PlannerInfo *root,
if (best_path->innersortkeys)
{
+ /*
+ * We do not consider incremental sort for inner path, because
+ * incremental sort does not support mark/restore.
+ */
+
Relids inner_relids = inner_path->parent->relids;
Sort *sort = make_sort_from_pathkeys(inner_plan,
best_path->innersortkeys,
@@ -5447,10 +5493,6 @@ label_sort_with_costsize(PlannerInfo *root, Sort *plan, double limit_tuples)
Plan *lefttree = plan->plan.lefttree;
Path sort_path; /* dummy for result of cost_sort */
- /*
- * This function shouldn't have to deal with IncrementalSort plans because
- * they are only created from corresponding Path nodes.
- */
Assert(IsA(plan, Sort));
cost_sort(&sort_path, root, NIL,
@@ -5470,6 +5512,37 @@ label_sort_with_costsize(PlannerInfo *root, Sort *plan, double limit_tuples)
}
/*
+ * Same as label_sort_with_costsize, but labels the IncrementalSort node
+ * instead.
+ */
+static void
+label_incrementalsort_with_costsize(PlannerInfo *root, IncrementalSort *plan,
+ List *pathkeys, double limit_tuples)
+{
+ Plan *lefttree = plan->sort.plan.lefttree;
+ Path sort_path; /* dummy for result of cost_incremental_sort */
+
+ Assert(IsA(plan, IncrementalSort));
+
+ cost_incremental_sort(&sort_path, root, pathkeys,
+ plan->nPresortedCols,
+ plan->sort.plan.disabled_nodes,
+ lefttree->startup_cost,
+ lefttree->total_cost,
+ lefttree->plan_rows,
+ lefttree->plan_width,
+ 0.0,
+ work_mem,
+ limit_tuples);
+ plan->sort.plan.startup_cost = sort_path.startup_cost;
+ plan->sort.plan.total_cost = sort_path.total_cost;
+ plan->sort.plan.plan_rows = lefttree->plan_rows;
+ plan->sort.plan.plan_width = lefttree->plan_width;
+ plan->sort.plan.parallel_aware = false;
+ plan->sort.plan.parallel_safe = lefttree->parallel_safe;
+}
+
+/*
* bitmap_subplan_mark_shared
* Set isshared flag in bitmap subplan so that it will be created in
* shared memory.