@@ -5102,8 +5102,9 @@ create_ordered_paths(PlannerInfo *root,
51025102 * have generated order-preserving Gather Merge plans which can be used
51035103 * without sorting if they happen to match the sort_pathkeys, and the loop
51045104 * above will have handled those as well. However, there's one more
5105- * possibility: it may make sense to sort the cheapest partial path
5106- * according to the required output order and then use Gather Merge.
5105+ * possibility: it may make sense to sort the cheapest partial path or
5106+ * incrementally sort any partial path that is partially sorted according
5107+ * to the required output order and then use Gather Merge.
51075108 */
51085109 if (ordered_rel -> consider_parallel && root -> sort_pathkeys != NIL &&
51095110 input_rel -> partial_pathlist != NIL )
@@ -5112,97 +5113,65 @@ create_ordered_paths(PlannerInfo *root,
51125113
51135114 cheapest_partial_path = linitial (input_rel -> partial_pathlist );
51145115
5115- /*
5116- * If cheapest partial path doesn't need a sort, this is redundant
5117- * with what's already been tried.
5118- */
5119- if (!pathkeys_contained_in (root -> sort_pathkeys ,
5120- cheapest_partial_path -> pathkeys ))
5116+ foreach (lc , input_rel -> partial_pathlist )
51215117 {
5122- Path * path ;
5118+ Path * input_path = (Path * ) lfirst (lc );
5119+ Path * sorted_path ;
5120+ bool is_sorted ;
5121+ int presorted_keys ;
51235122 double total_groups ;
51245123
5125- path = (Path * ) create_sort_path (root ,
5126- ordered_rel ,
5127- cheapest_partial_path ,
5128- root -> sort_pathkeys ,
5129- limit_tuples );
5130-
5131- total_groups = cheapest_partial_path -> rows *
5132- cheapest_partial_path -> parallel_workers ;
5133- path = (Path * )
5134- create_gather_merge_path (root , ordered_rel ,
5135- path ,
5136- path -> pathtarget ,
5137- root -> sort_pathkeys , NULL ,
5138- & total_groups );
5139-
5140- /* Add projection step if needed */
5141- if (path -> pathtarget != target )
5142- path = apply_projection_to_path (root , ordered_rel ,
5143- path , target );
5144-
5145- add_path (ordered_rel , path );
5146- }
5147-
5148- /*
5149- * Consider incremental sort with a gather merge on partial paths.
5150- *
5151- * We can also skip the entire loop when we only have a single-item
5152- * sort_pathkeys because then we can't possibly have a presorted
5153- * prefix of the list without having the list be fully sorted.
5154- */
5155- if (enable_incremental_sort && list_length (root -> sort_pathkeys ) > 1 )
5156- {
5157- foreach (lc , input_rel -> partial_pathlist )
5158- {
5159- Path * input_path = (Path * ) lfirst (lc );
5160- Path * sorted_path ;
5161- bool is_sorted ;
5162- int presorted_keys ;
5163- double total_groups ;
5164-
5165- /*
5166- * We don't care if this is the cheapest partial path - we
5167- * can't simply skip it, because it may be partially sorted in
5168- * which case we want to consider adding incremental sort
5169- * (instead of full sort, which is what happens above).
5170- */
5171-
5172- is_sorted = pathkeys_count_contained_in (root -> sort_pathkeys ,
5173- input_path -> pathkeys ,
5174- & presorted_keys );
5124+ is_sorted = pathkeys_count_contained_in (root -> sort_pathkeys ,
5125+ input_path -> pathkeys ,
5126+ & presorted_keys );
51755127
5176- /* No point in adding incremental sort on fully sorted paths. */
5177- if (is_sorted )
5178- continue ;
5128+ if (is_sorted )
5129+ continue ;
51795130
5180- if (presorted_keys == 0 )
5181- continue ;
5131+ /*
5132+ * Try at least sorting the cheapest path and also try
5133+ * incrementally sorting any path which is partially sorted
5134+ * already (no need to deal with paths which have presorted keys
5135+ * when incremental sort is disabled unless it's the cheapest
5136+ * partial path).
5137+ */
5138+ if (input_path != cheapest_partial_path &&
5139+ (presorted_keys == 0 || !enable_incremental_sort ))
5140+ continue ;
51825141
5183- /* Since we have presorted keys, consider incremental sort. */
5142+ /*
5143+ * We've no need to consider both a sort and incremental sort.
5144+ * We'll just do a sort if there are no presorted keys and an
5145+ * incremental sort when there are presorted keys.
5146+ */
5147+ if (presorted_keys == 0 || !enable_incremental_sort )
5148+ sorted_path = (Path * ) create_sort_path (root ,
5149+ ordered_rel ,
5150+ input_path ,
5151+ root -> sort_pathkeys ,
5152+ limit_tuples );
5153+ else
51845154 sorted_path = (Path * ) create_incremental_sort_path (root ,
51855155 ordered_rel ,
51865156 input_path ,
51875157 root -> sort_pathkeys ,
51885158 presorted_keys ,
51895159 limit_tuples );
5190- total_groups = input_path -> rows *
5191- input_path -> parallel_workers ;
5192- sorted_path = (Path * )
5193- create_gather_merge_path (root , ordered_rel ,
5194- sorted_path ,
5195- sorted_path -> pathtarget ,
5196- root -> sort_pathkeys , NULL ,
5197- & total_groups );
5198-
5199- /* Add projection step if needed */
5200- if (sorted_path -> pathtarget != target )
5201- sorted_path = apply_projection_to_path (root , ordered_rel ,
5202- sorted_path , target );
5203-
5204- add_path (ordered_rel , sorted_path );
5205- }
5160+ total_groups = input_path -> rows *
5161+ input_path -> parallel_workers ;
5162+ sorted_path = (Path * )
5163+ create_gather_merge_path (root , ordered_rel ,
5164+ sorted_path ,
5165+ sorted_path -> pathtarget ,
5166+ root -> sort_pathkeys , NULL ,
5167+ & total_groups );
5168+
5169+ /* Add projection step if needed */
5170+ if (sorted_path -> pathtarget != target )
5171+ sorted_path = apply_projection_to_path (root , ordered_rel ,
5172+ sorted_path , target );
5173+
5174+ add_path (ordered_rel , sorted_path );
52065175 }
52075176 }
52085177
@@ -7322,44 +7291,9 @@ gather_grouping_paths(PlannerInfo *root, RelOptInfo *rel)
73227291 /* Try Gather for unordered paths and Gather Merge for ordered ones. */
73237292 generate_useful_gather_paths (root , rel , true);
73247293
7325- /* Try cheapest partial path + explicit Sort + Gather Merge. */
73267294 cheapest_partial_path = linitial (rel -> partial_pathlist );
7327- if (!pathkeys_contained_in (root -> group_pathkeys ,
7328- cheapest_partial_path -> pathkeys ))
7329- {
7330- Path * path ;
7331- double total_groups ;
7332-
7333- total_groups =
7334- cheapest_partial_path -> rows * cheapest_partial_path -> parallel_workers ;
7335- path = (Path * ) create_sort_path (root , rel , cheapest_partial_path ,
7336- root -> group_pathkeys ,
7337- -1.0 );
7338- path = (Path * )
7339- create_gather_merge_path (root ,
7340- rel ,
7341- path ,
7342- rel -> reltarget ,
7343- root -> group_pathkeys ,
7344- NULL ,
7345- & total_groups );
73467295
7347- add_path (rel , path );
7348- }
7349-
7350- /*
7351- * Consider incremental sort on all partial paths, if enabled.
7352- *
7353- * We can also skip the entire loop when we only have a single-item
7354- * group_pathkeys because then we can't possibly have a presorted prefix
7355- * of the list without having the list be fully sorted.
7356- *
7357- * XXX Shouldn't this also consider the group-key-reordering?
7358- */
7359- if (!enable_incremental_sort || list_length (root -> group_pathkeys ) == 1 )
7360- return ;
7361-
7362- /* also consider incremental sort on partial paths, if enabled */
7296+ /* XXX Shouldn't this also consider the group-key-reordering? */
73637297 foreach (lc , rel -> partial_pathlist )
73647298 {
73657299 Path * path = (Path * ) lfirst (lc );
@@ -7374,15 +7308,34 @@ gather_grouping_paths(PlannerInfo *root, RelOptInfo *rel)
73747308 if (is_sorted )
73757309 continue ;
73767310
7377- if (presorted_keys == 0 )
7311+ /*
7312+ * Try at least sorting the cheapest path and also try incrementally
7313+ * sorting any path which is partially sorted already (no need to deal
7314+ * with paths which have presorted keys when incremental sort is
7315+ * disabled unless it's the cheapest input path).
7316+ */
7317+ if (path != cheapest_partial_path &&
7318+ (presorted_keys == 0 || !enable_incremental_sort ))
73787319 continue ;
73797320
7380- path = (Path * ) create_incremental_sort_path (root ,
7381- rel ,
7382- path ,
7383- root -> group_pathkeys ,
7384- presorted_keys ,
7385- -1.0 );
7321+ total_groups = path -> rows * path -> parallel_workers ;
7322+
7323+ /*
7324+ * We've no need to consider both a sort and incremental sort. We'll
7325+ * just do a sort if there are no presorted keys and an incremental
7326+ * sort when there are presorted keys.
7327+ */
7328+ if (presorted_keys == 0 || !enable_incremental_sort )
7329+ path = (Path * ) create_sort_path (root , rel , path ,
7330+ root -> group_pathkeys ,
7331+ -1.0 );
7332+ else
7333+ path = (Path * ) create_incremental_sort_path (root ,
7334+ rel ,
7335+ path ,
7336+ root -> group_pathkeys ,
7337+ presorted_keys ,
7338+ -1.0 );
73867339
73877340 path = (Path * )
73887341 create_gather_merge_path (root ,
0 commit comments