@@ -5102,8 +5102,9 @@ create_ordered_paths(PlannerInfo *root,
5102
5102
* have generated order-preserving Gather Merge plans which can be used
5103
5103
* without sorting if they happen to match the sort_pathkeys, and the loop
5104
5104
* 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.
5107
5108
*/
5108
5109
if (ordered_rel -> consider_parallel && root -> sort_pathkeys != NIL &&
5109
5110
input_rel -> partial_pathlist != NIL )
@@ -5112,97 +5113,65 @@ create_ordered_paths(PlannerInfo *root,
5112
5113
5113
5114
cheapest_partial_path = linitial (input_rel -> partial_pathlist );
5114
5115
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 )
5121
5117
{
5122
- Path * path ;
5118
+ Path * input_path = (Path * ) lfirst (lc );
5119
+ Path * sorted_path ;
5120
+ bool is_sorted ;
5121
+ int presorted_keys ;
5123
5122
double total_groups ;
5124
5123
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 );
5175
5127
5176
- /* No point in adding incremental sort on fully sorted paths. */
5177
- if (is_sorted )
5178
- continue ;
5128
+ if (is_sorted )
5129
+ continue ;
5179
5130
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 ;
5182
5141
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
5184
5154
sorted_path = (Path * ) create_incremental_sort_path (root ,
5185
5155
ordered_rel ,
5186
5156
input_path ,
5187
5157
root -> sort_pathkeys ,
5188
5158
presorted_keys ,
5189
5159
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 );
5206
5175
}
5207
5176
}
5208
5177
@@ -7322,44 +7291,9 @@ gather_grouping_paths(PlannerInfo *root, RelOptInfo *rel)
7322
7291
/* Try Gather for unordered paths and Gather Merge for ordered ones. */
7323
7292
generate_useful_gather_paths (root , rel , true);
7324
7293
7325
- /* Try cheapest partial path + explicit Sort + Gather Merge. */
7326
7294
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 );
7346
7295
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? */
7363
7297
foreach (lc , rel -> partial_pathlist )
7364
7298
{
7365
7299
Path * path = (Path * ) lfirst (lc );
@@ -7374,15 +7308,34 @@ gather_grouping_paths(PlannerInfo *root, RelOptInfo *rel)
7374
7308
if (is_sorted )
7375
7309
continue ;
7376
7310
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 ))
7378
7319
continue ;
7379
7320
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 );
7386
7339
7387
7340
path = (Path * )
7388
7341
create_gather_merge_path (root ,
0 commit comments