0001-Generalize-common-code-of-adding-sort-before-generat.patch
text/plain
Filename: 0001-Generalize-common-code-of-adding-sort-before-generat.patch
Type: text/plain
Part: 0
Message:
Re: POC: GROUP BY optimization
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch 0001
Subject: Generalize common code of adding sort before generation of grouping paths.
| File | + | − |
|---|---|---|
| src/backend/optimizer/plan/planner.c | 61 | 148 |
From ea068e221a754a463142575f6e0360d3118475f8 Mon Sep 17 00:00:00 2001
From: "Andrey V. Lepikhov" <a.lepikhov@postgrespro.ru>
Date: Tue, 9 Jan 2024 12:00:27 +0700
Subject: [PATCH 1/2] Generalize common code of adding sort before generation
of grouping paths.
---
src/backend/optimizer/plan/planner.c | 209 ++++++++-------------------
1 file changed, 61 insertions(+), 148 deletions(-)
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 667723b675..fcf647940e 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -6809,6 +6809,52 @@ done:
return parallel_workers;
}
+static Path *
+try_presorting(PlannerInfo *root, RelOptInfo *grouped_rel,
+ Path *path, Path *cheapest_path)
+{
+ bool is_sorted;
+ int presorted_keys;
+
+ is_sorted = pathkeys_count_contained_in(root->group_pathkeys,
+ path->pathkeys,
+ &presorted_keys);
+
+ if (!is_sorted)
+ {
+ /*
+ * Try at least sorting the cheapest path and also try
+ * incrementally sorting any path which is partially sorted
+ * already (no need to deal with paths which have presorted
+ * keys when incremental sort is disabled unless it's the
+ * cheapest input path).
+ */
+ if (path != cheapest_path &&
+ (presorted_keys == 0 || !enable_incremental_sort))
+ return NULL;
+
+ /*
+ * We've no need to consider both a sort and incremental sort.
+ * We'll just do a sort if there are no presorted keys and an
+ * incremental sort when there are presorted keys.
+ */
+ if (presorted_keys == 0 || !enable_incremental_sort)
+ path = (Path *) create_sort_path(root,
+ grouped_rel,
+ path,
+ root->group_pathkeys,
+ -1.0);
+ else
+ path = (Path *) create_incremental_sort_path(root,
+ grouped_rel,
+ path,
+ root->group_pathkeys,
+ presorted_keys,
+ -1.0);
+ }
+ return path;
+}
+
/*
* add_paths_to_grouping_rel
*
@@ -6840,45 +6886,11 @@ add_paths_to_grouping_rel(PlannerInfo *root, RelOptInfo *input_rel,
foreach(lc, input_rel->pathlist)
{
Path *path = (Path *) lfirst(lc);
- bool is_sorted;
- int presorted_keys;
-
- is_sorted = pathkeys_count_contained_in(root->group_pathkeys,
- path->pathkeys,
- &presorted_keys);
- if (!is_sorted)
- {
- /*
- * Try at least sorting the cheapest path and also try
- * incrementally sorting any path which is partially sorted
- * already (no need to deal with paths which have presorted
- * keys when incremental sort is disabled unless it's the
- * cheapest input path).
- */
- if (path != cheapest_path &&
- (presorted_keys == 0 || !enable_incremental_sort))
- continue;
+ path = try_presorting(root, grouped_rel, path, cheapest_path);
- /*
- * We've no need to consider both a sort and incremental sort.
- * We'll just do a sort if there are no presorted keys and an
- * incremental sort when there are presorted keys.
- */
- if (presorted_keys == 0 || !enable_incremental_sort)
- path = (Path *) create_sort_path(root,
- grouped_rel,
- path,
- root->group_pathkeys,
- -1.0);
- else
- path = (Path *) create_incremental_sort_path(root,
- grouped_rel,
- path,
- root->group_pathkeys,
- presorted_keys,
- -1.0);
- }
+ if (path == NULL)
+ continue;
/* Now decide what to stick atop it */
if (parse->groupingSets)
@@ -6935,46 +6947,12 @@ add_paths_to_grouping_rel(PlannerInfo *root, RelOptInfo *input_rel,
foreach(lc, partially_grouped_rel->pathlist)
{
Path *path = (Path *) lfirst(lc);
- bool is_sorted;
- int presorted_keys;
-
- is_sorted = pathkeys_count_contained_in(root->group_pathkeys,
- path->pathkeys,
- &presorted_keys);
- if (!is_sorted)
- {
- /*
- * Try at least sorting the cheapest path and also try
- * incrementally sorting any path which is partially
- * sorted already (no need to deal with paths which have
- * presorted keys when incremental sort is disabled unless
- * it's the cheapest input path).
- */
- if (path != partially_grouped_rel->cheapest_total_path &&
- (presorted_keys == 0 || !enable_incremental_sort))
- continue;
+ path = try_presorting(root, grouped_rel, path,
+ partially_grouped_rel->cheapest_total_path);
- /*
- * We've no need to consider both a sort and incremental
- * sort. We'll just do a sort if there are no pre-sorted
- * keys and an incremental sort when there are presorted
- * keys.
- */
- if (presorted_keys == 0 || !enable_incremental_sort)
- path = (Path *) create_sort_path(root,
- grouped_rel,
- path,
- root->group_pathkeys,
- -1.0);
- else
- path = (Path *) create_incremental_sort_path(root,
- grouped_rel,
- path,
- root->group_pathkeys,
- presorted_keys,
- -1.0);
- }
+ if (path == NULL)
+ continue;
if (parse->hasAggs)
add_path(grouped_rel, (Path *)
@@ -7200,44 +7178,12 @@ create_partial_grouping_paths(PlannerInfo *root,
foreach(lc, input_rel->pathlist)
{
Path *path = (Path *) lfirst(lc);
- bool is_sorted;
- int presorted_keys;
- is_sorted = pathkeys_count_contained_in(root->group_pathkeys,
- path->pathkeys,
- &presorted_keys);
- if (!is_sorted)
- {
- /*
- * Try at least sorting the cheapest path and also try
- * incrementally sorting any path which is partially sorted
- * already (no need to deal with paths which have presorted
- * keys when incremental sort is disabled unless it's the
- * cheapest input path).
- */
- if (path != cheapest_total_path &&
- (presorted_keys == 0 || !enable_incremental_sort))
- continue;
+ path = try_presorting(root, partially_grouped_rel, path,
+ cheapest_total_path);
- /*
- * We've no need to consider both a sort and incremental sort.
- * We'll just do a sort if there are no presorted keys and an
- * incremental sort when there are presorted keys.
- */
- if (presorted_keys == 0 || !enable_incremental_sort)
- path = (Path *) create_sort_path(root,
- partially_grouped_rel,
- path,
- root->group_pathkeys,
- -1.0);
- else
- path = (Path *) create_incremental_sort_path(root,
- partially_grouped_rel,
- path,
- root->group_pathkeys,
- presorted_keys,
- -1.0);
- }
+ if (path == NULL)
+ continue;
if (parse->hasAggs)
add_path(partially_grouped_rel, (Path *)
@@ -7268,45 +7214,12 @@ create_partial_grouping_paths(PlannerInfo *root,
foreach(lc, input_rel->partial_pathlist)
{
Path *path = (Path *) lfirst(lc);
- bool is_sorted;
- int presorted_keys;
- is_sorted = pathkeys_count_contained_in(root->group_pathkeys,
- path->pathkeys,
- &presorted_keys);
-
- if (!is_sorted)
- {
- /*
- * Try at least sorting the cheapest path and also try
- * incrementally sorting any path which is partially sorted
- * already (no need to deal with paths which have presorted
- * keys when incremental sort is disabled unless it's the
- * cheapest input path).
- */
- if (path != cheapest_partial_path &&
- (presorted_keys == 0 || !enable_incremental_sort))
- continue;
+ path = try_presorting(root, partially_grouped_rel, path,
+ cheapest_partial_path);
- /*
- * We've no need to consider both a sort and incremental sort.
- * We'll just do a sort if there are no presorted keys and an
- * incremental sort when there are presorted keys.
- */
- if (presorted_keys == 0 || !enable_incremental_sort)
- path = (Path *) create_sort_path(root,
- partially_grouped_rel,
- path,
- root->group_pathkeys,
- -1.0);
- else
- path = (Path *) create_incremental_sort_path(root,
- partially_grouped_rel,
- path,
- root->group_pathkeys,
- presorted_keys,
- -1.0);
- }
+ if (path == NULL)
+ continue;
if (parse->hasAggs)
add_partial_path(partially_grouped_rel, (Path *)
--
2.43.0