From ea068e221a754a463142575f6e0360d3118475f8 Mon Sep 17 00:00:00 2001 From: "Andrey V. Lepikhov" 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