parallel-incremental-sort-v3.patch
text/x-patch
Filename: parallel-incremental-sort-v3.patch
Type: text/x-patch
Part: 0
Patch
Format: unified
Series: patch v3
| File | + | − |
|---|---|---|
| src/backend/optimizer/path/costsize.c | 2 | 10 |
| src/backend/optimizer/plan/planner.c | 68 | 4 |
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index 7f820e7351..c6aa17ba67 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -1875,16 +1875,8 @@ cost_incremental_sort(Path *path,
limit_tuples);
/* If we have a LIMIT, adjust the number of groups we'll have to return. */
- if (limit_tuples > 0 && limit_tuples < input_tuples)
- {
- output_tuples = limit_tuples;
- output_groups = floor(output_tuples / group_tuples) + 1;
- }
- else
- {
- output_tuples = input_tuples;
- output_groups = input_groups;
- }
+ output_tuples = input_tuples;
+ output_groups = input_groups;
/*
* Startup cost of incremental sort is the startup cost of its first group
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 16996b1bc2..cb709b8764 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -5033,15 +5033,20 @@ create_ordered_paths(PlannerInfo *root,
input_rel->partial_pathlist != NIL)
{
Path *cheapest_partial_path;
+ bool is_sorted;
+ int presorted_keys;
cheapest_partial_path = linitial(input_rel->partial_pathlist);
+ is_sorted = pathkeys_common_contained_in(root->sort_pathkeys,
+ cheapest_partial_path->pathkeys,
+ &presorted_keys);
+
/*
* If cheapest partial path doesn't need a sort, this is redundant
* with what's already been tried.
*/
- if (!pathkeys_contained_in(root->sort_pathkeys,
- cheapest_partial_path->pathkeys))
+ if (!is_sorted)
{
Path *path;
double total_groups;
@@ -5067,6 +5072,34 @@ create_ordered_paths(PlannerInfo *root,
path, target);
add_path(ordered_rel, path);
+
+ /*
+ * If already partially sorted then we should also consider
+ * incremental sort.
+ */
+ if (presorted_keys > 0)
+ {
+ path = (Path *) create_incremental_sort_path(root,
+ ordered_rel,
+ cheapest_partial_path,
+ root->sort_pathkeys,
+ presorted_keys,
+ limit_tuples);
+
+ path = (Path *)
+ create_gather_merge_path(root, ordered_rel,
+ path,
+ path->pathtarget,
+ root->sort_pathkeys, NULL,
+ &total_groups);
+
+ /* Add projection step if needed */
+ if (path->pathtarget != target)
+ path = apply_projection_to_path(root, ordered_rel,
+ path, target);
+
+ add_path(ordered_rel, path);
+ }
}
}
@@ -6939,14 +6972,20 @@ static void
gather_grouping_paths(PlannerInfo *root, RelOptInfo *rel)
{
Path *cheapest_partial_path;
+ bool is_sorted;
+ int presorted_keys;
/* Try Gather for unordered paths and Gather Merge for ordered ones. */
generate_gather_paths(root, rel, true);
/* Try cheapest partial path + explicit Sort + Gather Merge. */
cheapest_partial_path = linitial(rel->partial_pathlist);
- if (!pathkeys_contained_in(root->group_pathkeys,
- cheapest_partial_path->pathkeys))
+
+ is_sorted = pathkeys_common_contained_in(root->group_pathkeys,
+ cheapest_partial_path->pathkeys,
+ &presorted_keys);
+
+ if (!is_sorted)
{
Path *path;
double total_groups;
@@ -6966,6 +7005,31 @@ gather_grouping_paths(PlannerInfo *root, RelOptInfo *rel)
&total_groups);
add_path(rel, path);
+
+ /*
+ * If already partially sorted then we should also consider
+ * incremental sort.
+ */
+ if (presorted_keys > 0)
+ {
+ path = (Path *) create_incremental_sort_path(root,
+ rel,
+ cheapest_partial_path,
+ root->group_pathkeys,
+ presorted_keys,
+ -1.0);
+
+ path = (Path *)
+ create_gather_merge_path(root,
+ rel,
+ path,
+ rel->reltarget,
+ root->group_pathkeys,
+ NULL,
+ &total_groups);
+
+ add_path(rel, path);
+ }
}
}