* 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,
* (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
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 */
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 */
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)
{
* 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
* 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,
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
* clauses have been applied (ie, output rows of a plan for it)
* width - avg. number of bytes per tuple in the relation after the
* appropriate projections have been done (ie, output width)
+ * consider_startup - true if there is any value in keeping paths for
+ * this rel on the basis of having cheap startup cost
* reltargetlist - List of Var and PlaceHolderVar nodes for the values
* we need to output from this relation.
* List is in no particular order, but all rels of an
double rows; /* estimated number of result tuples */
int width; /* estimated avg width of result tuples */
+ /* per-relation planner control flags */
+ bool consider_startup; /* keep cheap-startup-cost paths? */
+
/* materialization information */
List *reltargetlist; /* Vars to be output by scan of relation */
List *pathlist; /* Path structures */
create temp table dual();
insert into dual default values;
+analyze dual;
select v.* from
(int8_tbl x left join (select q1,(select coalesce(q2,0)) q2 from int8_tbl) y on x.q2 = y.q1)
left join int4_tbl z on z.f1 = x.q2,
123 |
456 |
123 | 4567890123456789
- 4567890123456789 | 123
+ 4567890123456789 | -4567890123456789
123 | 4567890123456789
4567890123456789 | 4567890123456789
123 | 4567890123456789
- 4567890123456789 | -4567890123456789
4567890123456789 | 123
- 123 | 456
4567890123456789 | 123
123 | 4567890123456789
- 4567890123456789 | 4567890123456789
4567890123456789 | 123
+ 123 | 456
4567890123456789 | 4567890123456789
+ 4567890123456789 | -4567890123456789
4567890123456789 | 4567890123456789
4567890123456789 | 4567890123456789
- 4567890123456789 | -4567890123456789
+ 4567890123456789 | 4567890123456789
+ 4567890123456789 | 123
4567890123456789 |
-4567890123456789 |
(20 rows)