]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Avoid creating duplicate ordered append paths
authorRichard Guo <rguo@postgresql.org>
Wed, 5 Nov 2025 09:10:54 +0000 (18:10 +0900)
committerRichard Guo <rguo@postgresql.org>
Wed, 5 Nov 2025 09:10:54 +0000 (18:10 +0900)
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

src/backend/optimizer/path/allpaths.c

index 41233b983737c09cbcca78cefb7a4dc2749338fc..4c43fd0b19b2343a40c264c381ac591704a3878b 100644 (file)
@@ -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,