summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Guo <rguo@postgresql.org>2025-11-05 18:10:54 +0900
committerRichard Guo <rguo@postgresql.org>2025-11-05 18:10:54 +0900
commit0ea5eee37606386150aa8317184617e1d5d34565 (patch)
tree4a4a11595db2e554055c55ab104729a6e926ef68
parentc1777f2d6d43adf9bc65da3e44a3a5ad2cbfa86d (diff)
Avoid creating duplicate ordered append paths
In generate_orderedappend_paths(), the function does not handle the case where the paths in total_subpaths and fractional_subpaths are identical. This situation is not uncommon, and as a result, it may generate two exactly identical ordered append paths. Fix by checking whether total_subpaths and fractional_subpaths contain the same paths, and skipping creation of the ordered append path for the fractional case when they are identical. Given the lack of field complaints about this, I'm a bit hesitant to back-patch, but let's clean it up in HEAD. Author: Richard Guo <guofenglinux@gmail.com> Reviewed-by: Andrei Lepikhov <lepihov@gmail.com> Reviewed-by: Alexander Korotkov <aekorotkov@gmail.com> Discussion: https://postgr.es/m/CAMbWs4-OYsgA75tGGiBARt87G0y_z_GBTSLrzudcJxAzndYkYw@mail.gmail.com
-rw-r--r--src/backend/optimizer/path/allpaths.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 41233b98373..4c43fd0b19b 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -1877,6 +1877,7 @@ generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel,
List *total_subpaths = NIL;
List *fractional_subpaths = NIL;
bool startup_neq_total = false;
+ bool fraction_neq_total = false;
bool match_partition_order;
bool match_partition_order_desc;
int end_index;
@@ -2005,15 +2006,21 @@ generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel,
* XXX We might consider partially sorted paths too (with an
* incremental sort on top). But we'd have to build all the
* incremental paths, do the costing etc.
+ *
+ * Also, notice whether we actually have different paths for
+ * the "fractional" and "total" cases. This helps avoid
+ * generating two identical ordered append paths.
*/
- if (!cheapest_fractional)
+ if (cheapest_fractional == NULL)
cheapest_fractional = cheapest_total;
+ else if (cheapest_fractional != cheapest_total)
+ fraction_neq_total = true;
}
/*
* Notice whether we actually have different paths for the
- * "cheapest" and "total" cases; frequently there will be no point
- * in two create_merge_append_path() calls.
+ * "cheapest" and "total" cases. This helps avoid generating two
+ * identical ordered append paths.
*/
if (cheapest_startup != cheapest_total)
startup_neq_total = true;
@@ -2084,7 +2091,7 @@ generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel,
false,
-1));
- if (fractional_subpaths)
+ if (fractional_subpaths && fraction_neq_total)
add_path(rel, (Path *) create_append_path(root,
rel,
fractional_subpaths,
@@ -2110,7 +2117,7 @@ generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel,
pathkeys,
NULL));
- if (fractional_subpaths)
+ if (fractional_subpaths && fraction_neq_total)
add_path(rel, (Path *) create_merge_append_path(root,
rel,
fractional_subpaths,