mirror of
https://github.com/postgres/postgres.git
synced 2025-08-27 07:42:10 +03:00
Consider fractional paths in generate_orderedappend_paths
When building append paths, we've been looking only at startup and total costs for the paths. When building fractional paths that may eliminate the cheapest one, because it may be dominated by two separate paths (one for startup, one for total cost). This extends generate_orderedappend_paths() to also consider which paths have lowest fractional cost. Currently we only consider paths matching pathkeys - in the future this may be improved by also considering paths that are only partially sorted, with an incremental sort on top. Original report of an issue by Arne Roland, patch by me (based on a suggestion by Tom Lane). Reviewed-by: Arne Roland, Zhihong Yu Discussion: https://postgr.es/m/e8f9ec90-546d-e948-acce-0525f3e92773%40enterprisedb.com Discussion: https://postgr.es/m/1581042da8044e71ada2d6e3a51bf7bb%40index.de
This commit is contained in:
@@ -1716,6 +1716,7 @@ generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel,
|
||||
List *pathkeys = (List *) lfirst(lcp);
|
||||
List *startup_subpaths = NIL;
|
||||
List *total_subpaths = NIL;
|
||||
List *fractional_subpaths = NIL;
|
||||
bool startup_neq_total = false;
|
||||
ListCell *lcr;
|
||||
bool match_partition_order;
|
||||
@@ -1745,7 +1746,8 @@ generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel,
|
||||
{
|
||||
RelOptInfo *childrel = (RelOptInfo *) lfirst(lcr);
|
||||
Path *cheapest_startup,
|
||||
*cheapest_total;
|
||||
*cheapest_total,
|
||||
*cheapest_fractional = NULL;
|
||||
|
||||
/* Locate the right paths, if they are available. */
|
||||
cheapest_startup =
|
||||
@@ -1773,6 +1775,37 @@ generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel,
|
||||
Assert(cheapest_total->param_info == NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* When building a fractional path, determine a cheapest fractional
|
||||
* path for each child relation too. Looking at startup and total
|
||||
* costs is not enough, because the cheapest fractional path may be
|
||||
* dominated by two separate paths (one for startup, one for total).
|
||||
*
|
||||
* When needed (building fractional path), determine the cheapest
|
||||
* fractional path too.
|
||||
*/
|
||||
if (root->tuple_fraction > 0)
|
||||
{
|
||||
double path_fraction = (1.0 / root->tuple_fraction);
|
||||
|
||||
cheapest_fractional =
|
||||
get_cheapest_fractional_path_for_pathkeys(childrel->pathlist,
|
||||
pathkeys,
|
||||
NULL,
|
||||
path_fraction);
|
||||
|
||||
/*
|
||||
* If we found no path with matching pathkeys, use the cheapest
|
||||
* total path instead.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
if (!cheapest_fractional)
|
||||
cheapest_fractional = cheapest_total;
|
||||
}
|
||||
|
||||
/*
|
||||
* Notice whether we actually have different paths for the
|
||||
* "cheapest" and "total" cases; frequently there will be no point
|
||||
@@ -1799,6 +1832,12 @@ generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel,
|
||||
|
||||
startup_subpaths = lappend(startup_subpaths, cheapest_startup);
|
||||
total_subpaths = lappend(total_subpaths, cheapest_total);
|
||||
|
||||
if (cheapest_fractional)
|
||||
{
|
||||
cheapest_fractional = get_singleton_append_subpath(cheapest_fractional);
|
||||
fractional_subpaths = lappend(fractional_subpaths, cheapest_fractional);
|
||||
}
|
||||
}
|
||||
else if (match_partition_order_desc)
|
||||
{
|
||||
@@ -1812,6 +1851,12 @@ generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel,
|
||||
|
||||
startup_subpaths = lcons(cheapest_startup, startup_subpaths);
|
||||
total_subpaths = lcons(cheapest_total, total_subpaths);
|
||||
|
||||
if (cheapest_fractional)
|
||||
{
|
||||
cheapest_fractional = get_singleton_append_subpath(cheapest_fractional);
|
||||
fractional_subpaths = lcons(cheapest_fractional, fractional_subpaths);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1823,6 +1868,10 @@ generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel,
|
||||
&startup_subpaths, NULL);
|
||||
accumulate_append_subpath(cheapest_total,
|
||||
&total_subpaths, NULL);
|
||||
|
||||
if (cheapest_fractional)
|
||||
accumulate_append_subpath(cheapest_fractional,
|
||||
&fractional_subpaths, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1849,6 +1898,17 @@ generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel,
|
||||
0,
|
||||
false,
|
||||
-1));
|
||||
|
||||
if (fractional_subpaths)
|
||||
add_path(rel, (Path *) create_append_path(root,
|
||||
rel,
|
||||
fractional_subpaths,
|
||||
NIL,
|
||||
pathkeys,
|
||||
NULL,
|
||||
0,
|
||||
false,
|
||||
-1));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1864,6 +1924,13 @@ generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel,
|
||||
total_subpaths,
|
||||
pathkeys,
|
||||
NULL));
|
||||
|
||||
if (fractional_subpaths)
|
||||
add_path(rel, (Path *) create_merge_append_path(root,
|
||||
rel,
|
||||
fractional_subpaths,
|
||||
pathkeys,
|
||||
NULL));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user