aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/pathnode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/util/pathnode.c')
-rw-r--r--src/backend/optimizer/util/pathnode.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index 8677ff20fd5..d827b4959b6 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -139,6 +139,9 @@ compare_fractional_path_costs(Path *path1, Path *path2,
* total cost, we just say that their costs are "different", since neither
* dominates the other across the whole performance spectrum.
*
+ * If consider_startup is false, then we don't care about keeping paths with
+ * good startup cost, so we'll never return COSTS_DIFFERENT.
+ *
* This function also includes special hacks to support a policy enforced
* by its sole caller, add_path(): paths that have any parameterization
* cannot win comparisons on the grounds of having cheaper startup cost,
@@ -146,7 +149,8 @@ compare_fractional_path_costs(Path *path1, Path *path2,
* (Unparameterized paths are more common, so we check for this case last.)
*/
static PathCostComparison
-compare_path_costs_fuzzily(Path *path1, Path *path2, double fuzz_factor)
+compare_path_costs_fuzzily(Path *path1, Path *path2, double fuzz_factor,
+ bool consider_startup)
{
/*
* Check total cost first since it's more likely to be different; many
@@ -155,7 +159,8 @@ compare_path_costs_fuzzily(Path *path1, Path *path2, double fuzz_factor)
if (path1->total_cost > path2->total_cost * fuzz_factor)
{
/* path1 fuzzily worse on total cost */
- if (path2->startup_cost > path1->startup_cost * fuzz_factor &&
+ if (consider_startup &&
+ path2->startup_cost > path1->startup_cost * fuzz_factor &&
path1->param_info == NULL)
{
/* ... but path2 fuzzily worse on startup, so DIFFERENT */
@@ -167,7 +172,8 @@ compare_path_costs_fuzzily(Path *path1, Path *path2, double fuzz_factor)
if (path2->total_cost > path1->total_cost * fuzz_factor)
{
/* path2 fuzzily worse on total cost */
- if (path1->startup_cost > path2->startup_cost * fuzz_factor &&
+ if (consider_startup &&
+ path1->startup_cost > path2->startup_cost * fuzz_factor &&
path2->param_info == NULL)
{
/* ... but path1 fuzzily worse on startup, so DIFFERENT */
@@ -177,6 +183,7 @@ compare_path_costs_fuzzily(Path *path1, Path *path2, double fuzz_factor)
return COSTS_BETTER1;
}
/* fuzzily the same on total cost */
+ /* (so we may as well compare startup cost, even if !consider_startup) */
if (path1->startup_cost > path2->startup_cost * fuzz_factor &&
path2->param_info == NULL)
{
@@ -360,6 +367,9 @@ set_cheapest(RelOptInfo *parent_rel)
* reduce the number of parameterized paths that are kept. See discussion
* in src/backend/optimizer/README.
*
+ * Another policy that is enforced here is that we only consider cheap
+ * startup cost to be interesting if parent_rel->consider_startup is true.
+ *
* The pathlist is kept sorted by total_cost, with cheaper paths
* at the front. Within this routine, that's simply a speed hack:
* doing it that way makes it more likely that we will reject an inferior
@@ -423,7 +433,8 @@ add_path(RelOptInfo *parent_rel, Path *new_path)
* Do a fuzzy cost comparison with 1% fuzziness limit. (XXX does this
* percentage need to be user-configurable?)
*/
- costcmp = compare_path_costs_fuzzily(new_path, old_path, 1.01);
+ costcmp = compare_path_costs_fuzzily(new_path, old_path, 1.01,
+ parent_rel->consider_startup);
/*
* If the two paths compare differently for startup and total cost,
@@ -488,8 +499,10 @@ add_path(RelOptInfo *parent_rel, Path *new_path)
remove_old = true; /* new dominates old */
else if (new_path->rows > old_path->rows)
accept_new = false; /* old dominates new */
- else if (compare_path_costs_fuzzily(new_path, old_path,
- 1.0000000001) == COSTS_BETTER1)
+ else if (compare_path_costs_fuzzily(new_path,
+ old_path,
+ 1.0000000001,
+ parent_rel->consider_startup) == COSTS_BETTER1)
remove_old = true; /* new dominates old */
else
accept_new = false; /* old equals or