From eba72b5998d8d51605c6fea535569464c3a4770f Mon Sep 17 00:00:00 2001 From: Richard Guo Date: Tue, 10 Jan 2023 17:17:14 +0800 Subject: [PATCH v1 3/3] Revise how we sort partial paths in gather_grouping_paths --- src/backend/optimizer/plan/planner.c | 68 +++++++++++----------------- 1 file changed, 27 insertions(+), 41 deletions(-) diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 9f22bcbf1a..29fa2e6bcc 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -7191,42 +7191,8 @@ gather_grouping_paths(PlannerInfo *root, RelOptInfo *rel) /* Try Gather for unordered paths and Gather Merge for ordered ones. */ generate_useful_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)) - { - Path *path; - double total_groups; - - total_groups = - cheapest_partial_path->rows * cheapest_partial_path->parallel_workers; - path = (Path *) create_sort_path(root, rel, cheapest_partial_path, - root->group_pathkeys, - -1.0); - path = (Path *) - create_gather_merge_path(root, - rel, - path, - rel->reltarget, - root->group_pathkeys, - NULL, - &total_groups); - - add_path(rel, path); - } - - /* - * Consider incremental sort on all partial paths, if enabled. - * - * We can also skip the entire loop when we only have a single-item - * group_pathkeys because then we can't possibly have a presorted prefix - * of the list without having the list be fully sorted. - */ - if (!enable_incremental_sort || list_length(root->group_pathkeys) == 1) - return; - /* also consider incremental sort on partial paths, if enabled */ foreach(lc, rel->partial_pathlist) { Path *path = (Path *) lfirst(lc); @@ -7241,15 +7207,35 @@ gather_grouping_paths(PlannerInfo *root, RelOptInfo *rel) if (is_sorted) continue; - if (presorted_keys == 0) + /* + * 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 = (Path *) create_incremental_sort_path(root, - rel, - path, - root->group_pathkeys, - presorted_keys, - -1.0); + total_groups = path->rows * path->parallel_workers; + + /* + * 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, + root->group_pathkeys, + -1.0); + else + path = (Path *) create_incremental_sort_path(root, + rel, + path, + root->group_pathkeys, + presorted_keys, + -1.0); path = (Path *) create_gather_merge_path(root, -- 2.31.0