Fix tuple_fraction calculation in generate_orderedappend_paths() master github/master
authorAlexander Korotkov <[email protected]>
Sun, 18 May 2025 20:49:50 +0000 (23:49 +0300)
committerAlexander Korotkov <[email protected]>
Sun, 18 May 2025 20:49:50 +0000 (23:49 +0300)
6b94e7a6da adjusted generate_orderedappend_paths() to consider fractional
paths.  However, it didn't manage to interpret the tuple_fraction value
correctly.  According to the header comment of grouping_planner(), the
tuple_fraction >= 1 specifies the absolute number of expected tuples.  That
number must be divided by the expected total number of tuples to get the
actual fraction.

Even though this is a bug fix, we don't backpatch it.  The risks of the side
effects of plan changes on stable branches are too high.

Reported-by: Andrei Lepikhov <[email protected]>
Discussion: https://postgr.es/m/3ca271fa-ca5c-458c-8934-eb148622b270%40gmail.com
Author: Andrei Lepikhov <[email protected]>
Reviewed-by: Junwang Zhao <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Tom Lane <[email protected]>
src/backend/optimizer/path/allpaths.c
src/test/regress/expected/partition_join.out
src/test/regress/sql/partition_join.sql

index 905250b3325251e121f6b09a79c995ae77b1aea6..6cc6966b0600acb3fda3b8cafd1e2ec6c700fb7a 100644 (file)
@@ -1891,7 +1891,17 @@ generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel,
             */
            if (root->tuple_fraction > 0)
            {
             */
            if (root->tuple_fraction > 0)
            {
-               double      path_fraction = (1.0 / root->tuple_fraction);
+               double      path_fraction = root->tuple_fraction;
+
+               /*
+                * Merge Append considers only live children relations.  Dummy
+                * relations must be filtered out before.
+                */
+               Assert(childrel->rows > 0);
+
+               /* Convert absolute limit to a path fraction */
+               if (path_fraction >= 1.0)
+                   path_fraction /= childrel->rows;
 
                cheapest_fractional =
                    get_cheapest_fractional_path_for_pathkeys(childrel->pathlist,
 
                cheapest_fractional =
                    get_cheapest_fractional_path_for_pathkeys(childrel->pathlist,
index 6101c8c7cf10841c19cf2573280ae952762d459e..d5368186caa9f0b97cd50d4b4a54151f402afa88 100644 (file)
@@ -5260,6 +5260,24 @@ SELECT x.id, y.id FROM fract_t x LEFT JOIN fract_t y USING (id) ORDER BY x.id DE
                      Index Cond: (id = x_2.id)
 (11 rows)
 
                      Index Cond: (id = x_2.id)
 (11 rows)
 
+EXPLAIN (COSTS OFF) -- Should use NestLoop with parameterised inner scan
+SELECT x.id, y.id FROM fract_t x LEFT JOIN fract_t y USING (id)
+ORDER BY x.id DESC LIMIT 2;
+                                   QUERY PLAN                                   
+--------------------------------------------------------------------------------
+ Limit
+   ->  Merge Append
+         Sort Key: x.id DESC
+         ->  Nested Loop Left Join
+               ->  Index Only Scan Backward using fract_t0_pkey on fract_t0 x_1
+               ->  Index Only Scan using fract_t0_pkey on fract_t0 y_1
+                     Index Cond: (id = x_1.id)
+         ->  Nested Loop Left Join
+               ->  Index Only Scan Backward using fract_t1_pkey on fract_t1 x_2
+               ->  Index Only Scan using fract_t1_pkey on fract_t1 y_2
+                     Index Cond: (id = x_2.id)
+(11 rows)
+
 --
 -- Test Append's fractional paths
 --
 --
 -- Test Append's fractional paths
 --
index b76c545100126ff1554ae2b4f6d10139dd4d4011..30f15ee9acb5a5e3b8463e457e65891f23e32a57 100644 (file)
@@ -1224,6 +1224,9 @@ SELECT x.id, y.id FROM fract_t x LEFT JOIN fract_t y USING (id) ORDER BY x.id AS
 
 EXPLAIN (COSTS OFF)
 SELECT x.id, y.id FROM fract_t x LEFT JOIN fract_t y USING (id) ORDER BY x.id DESC LIMIT 10;
 
 EXPLAIN (COSTS OFF)
 SELECT x.id, y.id FROM fract_t x LEFT JOIN fract_t y USING (id) ORDER BY x.id DESC LIMIT 10;
+EXPLAIN (COSTS OFF) -- Should use NestLoop with parameterised inner scan
+SELECT x.id, y.id FROM fract_t x LEFT JOIN fract_t y USING (id)
+ORDER BY x.id DESC LIMIT 2;
 
 --
 -- Test Append's fractional paths
 
 --
 -- Test Append's fractional paths