0001-Generalize-common-code-of-adding-sort-befor-20240115.patch
application/octet-stream
Filename: 0001-Generalize-common-code-of-adding-sort-befor-20240115.patch
Type: application/octet-stream
Part: 1
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 | 80 | 148 |
From 2167ada5fc9e2d07b1f20cd840bea409e0e594c9 Mon Sep 17 00:00:00 2001
From: Alexander Korotkov <akorotkov@postgresql.org>
Date: Thu, 11 Jan 2024 13:27:58 +0200
Subject: [PATCH 1/2] Generalize common code of adding sort before generation
of grouping paths
Extract the repetitive code pattern into a new function make_ordered_path().
Discussion: https://postgr.es/m/CAPpHfdtzaVa7S4onKy3YvttF2rrH5hQNHx9HtcSTLbpjx%2BMJ%2Bw%40mail.gmail.com
Author: Andrei Lepikhov
---
src/backend/optimizer/plan/planner.c | 228 ++++++++++-----------------
1 file changed, 80 insertions(+), 148 deletions(-)
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 667723b6753..014b179c3f0 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -6809,6 +6809,58 @@ done:
return parallel_workers;
}
+/*
+ * make_ordered_path
+ * Return a path ordered by 'pathkeys' based on the given 'path'. May
+ * return NULL if it doesn't make sense to generate an ordered path in
+ * this case.
+ */
+static Path *
+make_ordered_path(PlannerInfo *root, RelOptInfo *rel, Path *path,
+ Path *cheapest_path, List *pathkeys)
+{
+ bool is_sorted;
+ int presorted_keys;
+
+ is_sorted = pathkeys_count_contained_in(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,
+ rel,
+ path,
+ pathkeys,
+ -1.0);
+ else
+ path = (Path *) create_incremental_sort_path(root,
+ rel,
+ path,
+ pathkeys,
+ presorted_keys,
+ -1.0);
+ }
+
+ return path;
+}
+
/*
* add_paths_to_grouping_rel
*
@@ -6840,45 +6892,15 @@ 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 = make_ordered_path(root,
+ grouped_rel,
+ path,
+ cheapest_path,
+ root->group_pathkeys);
- /*
- * 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 +6957,15 @@ 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 = make_ordered_path(root,
+ grouped_rel,
+ path,
+ partially_grouped_rel->cheapest_total_path,
+ root->group_pathkeys);
- /*
- * 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 +7191,15 @@ 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 = make_ordered_path(root,
+ partially_grouped_rel,
+ path,
+ cheapest_total_path,
+ root->group_pathkeys);
- /*
- * 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 +7230,15 @@ 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 = make_ordered_path(root,
+ partially_grouped_rel,
+ path,
+ cheapest_partial_path,
+ root->group_pathkeys);
- /*
- * 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.39.3 (Apple Git-145)