diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 9c6436eb72f..41233b98373 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1810,9 +1810,11 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, * We generate a path for each ordering (pathkey list) appearing in * all_child_pathkeys. * - * We consider both cheapest-startup and cheapest-total cases, ie, for each - * interesting ordering, collect all the cheapest startup subpaths and all the - * cheapest total paths, and build a suitable path for each case. + * We consider the cheapest-startup and cheapest-total cases, and also the + * cheapest-fractional case when not all tuples need to be retrieved. For each + * interesting ordering, we collect all the cheapest startup subpaths, all the + * cheapest total paths, and, if applicable, all the cheapest fractional paths, + * and build a suitable path for each case. * * We don't currently generate any parameterized ordered paths here. While * it would not take much more code here to do so, it's very unclear that it @@ -1977,14 +1979,18 @@ generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel, double path_fraction = root->tuple_fraction; /* - * Merge Append considers only live children relations. Dummy - * relations must be filtered out before. + * We should not have a dummy child relation here. However, + * we cannot use childrel->rows to compute the tuple fraction, + * as childrel can be an upper relation with an unset row + * estimate. Instead, we use the row estimate from the + * cheapest_total path, which should already have been forced + * to a sane value. */ - Assert(childrel->rows > 0); + Assert(cheapest_total->rows > 0); /* Convert absolute limit to a path fraction */ if (path_fraction >= 1.0) - path_fraction /= childrel->rows; + path_fraction /= cheapest_total->rows; cheapest_fractional = get_cheapest_fractional_path_for_pathkeys(childrel->pathlist, diff --git a/src/test/regress/expected/partition_aggregate.out b/src/test/regress/expected/partition_aggregate.out index fc84929a002..c30304b99c7 100644 --- a/src/test/regress/expected/partition_aggregate.out +++ b/src/test/regress/expected/partition_aggregate.out @@ -339,6 +339,37 @@ SELECT a FROM pagg_tab WHERE a < 3 GROUP BY a ORDER BY 1; 2 (3 rows) +-- Test partitionwise aggregation with ordered append path built from fractional paths +EXPLAIN (COSTS OFF) +SELECT count(*) FROM pagg_tab GROUP BY c ORDER BY c LIMIT 1; + QUERY PLAN +------------------------------------------------------------ + Limit + -> Merge Append + Sort Key: pagg_tab.c + -> GroupAggregate + Group Key: pagg_tab.c + -> Sort + Sort Key: pagg_tab.c + -> Seq Scan on pagg_tab_p1 pagg_tab + -> GroupAggregate + Group Key: pagg_tab_1.c + -> Sort + Sort Key: pagg_tab_1.c + -> Seq Scan on pagg_tab_p2 pagg_tab_1 + -> GroupAggregate + Group Key: pagg_tab_2.c + -> Sort + Sort Key: pagg_tab_2.c + -> Seq Scan on pagg_tab_p3 pagg_tab_2 +(18 rows) + +SELECT count(*) FROM pagg_tab GROUP BY c ORDER BY c LIMIT 1; + count +------- + 250 +(1 row) + RESET enable_hashagg; -- ROLLUP, partitionwise aggregation does not apply EXPLAIN (COSTS OFF) diff --git a/src/test/regress/sql/partition_aggregate.sql b/src/test/regress/sql/partition_aggregate.sql index 124cc260461..7c725e2663a 100644 --- a/src/test/regress/sql/partition_aggregate.sql +++ b/src/test/regress/sql/partition_aggregate.sql @@ -76,6 +76,11 @@ EXPLAIN (COSTS OFF) SELECT a FROM pagg_tab WHERE a < 3 GROUP BY a ORDER BY 1; SELECT a FROM pagg_tab WHERE a < 3 GROUP BY a ORDER BY 1; +-- Test partitionwise aggregation with ordered append path built from fractional paths +EXPLAIN (COSTS OFF) +SELECT count(*) FROM pagg_tab GROUP BY c ORDER BY c LIMIT 1; +SELECT count(*) FROM pagg_tab GROUP BY c ORDER BY c LIMIT 1; + RESET enable_hashagg; -- ROLLUP, partitionwise aggregation does not apply