@@ -125,8 +125,11 @@ compare_fractional_path_costs(Path *path1, Path *path2,
125
125
*
126
126
* We use fuzzy comparisons so that add_path() can avoid keeping both of
127
127
* a pair of paths that really have insignificantly different cost.
128
- * The fuzz factor is 1% of the smaller cost. (XXX does this percentage
129
- * need to be user-configurable?)
128
+ *
129
+ * The fuzz_factor argument must be 1.0 plus delta, where delta is the
130
+ * fraction of the smaller cost that is considered to be a significant
131
+ * difference. For example, fuzz_factor = 1.01 makes the fuzziness limit
132
+ * be 1% of the smaller cost.
130
133
*
131
134
* The two paths are said to have "equal" costs if both startup and total
132
135
* costs are fuzzily the same. Path1 is said to be better than path2 if
@@ -138,27 +141,27 @@ compare_fractional_path_costs(Path *path1, Path *path2,
138
141
* dominates the other across the whole performance spectrum.
139
142
*/
140
143
static PathCostComparison
141
- compare_path_costs_fuzzily (Path * path1 , Path * path2 )
144
+ compare_path_costs_fuzzily (Path * path1 , Path * path2 , double fuzz_factor )
142
145
{
143
146
/*
144
147
* Check total cost first since it's more likely to be different; many
145
148
* paths have zero startup cost.
146
149
*/
147
- if (path1 -> total_cost > path2 -> total_cost * 1.01 )
150
+ if (path1 -> total_cost > path2 -> total_cost * fuzz_factor )
148
151
{
149
152
/* path1 fuzzily worse on total cost */
150
- if (path2 -> startup_cost > path1 -> startup_cost * 1.01 )
153
+ if (path2 -> startup_cost > path1 -> startup_cost * fuzz_factor )
151
154
{
152
155
/* ... but path2 fuzzily worse on startup, so DIFFERENT */
153
156
return COSTS_DIFFERENT ;
154
157
}
155
158
/* else path2 dominates */
156
159
return COSTS_BETTER2 ;
157
160
}
158
- if (path2 -> total_cost > path1 -> total_cost * 1.01 )
161
+ if (path2 -> total_cost > path1 -> total_cost * fuzz_factor )
159
162
{
160
163
/* path2 fuzzily worse on total cost */
161
- if (path1 -> startup_cost > path2 -> startup_cost * 1.01 )
164
+ if (path1 -> startup_cost > path2 -> startup_cost * fuzz_factor )
162
165
{
163
166
/* ... but path1 fuzzily worse on startup, so DIFFERENT */
164
167
return COSTS_DIFFERENT ;
@@ -167,12 +170,12 @@ compare_path_costs_fuzzily(Path *path1, Path *path2)
167
170
return COSTS_BETTER1 ;
168
171
}
169
172
/* fuzzily the same on total cost */
170
- if (path1 -> startup_cost > path2 -> startup_cost * 1.01 )
173
+ if (path1 -> startup_cost > path2 -> startup_cost * fuzz_factor )
171
174
{
172
175
/* ... but path1 fuzzily worse on startup, so path2 wins */
173
176
return COSTS_BETTER2 ;
174
177
}
175
- if (path2 -> startup_cost > path1 -> startup_cost * 1.01 )
178
+ if (path2 -> startup_cost > path1 -> startup_cost * fuzz_factor )
176
179
{
177
180
/* ... but path2 fuzzily worse on startup, so path1 wins */
178
181
return COSTS_BETTER1 ;
@@ -354,7 +357,11 @@ add_path(RelOptInfo *parent_rel, Path *new_path)
354
357
355
358
p1_next = lnext (p1 );
356
359
357
- costcmp = compare_path_costs_fuzzily (new_path , old_path );
360
+ /*
361
+ * Do a fuzzy cost comparison with 1% fuzziness limit. (XXX does this
362
+ * percentage need to be user-configurable?)
363
+ */
364
+ costcmp = compare_path_costs_fuzzily (new_path , old_path , 1.01 );
358
365
359
366
/*
360
367
* If the two paths compare differently for startup and total cost,
@@ -403,15 +410,24 @@ add_path(RelOptInfo *parent_rel, Path *new_path)
403
410
/*
404
411
* Same pathkeys and outer rels, and fuzzily
405
412
* the same cost, so keep just one; to decide
406
- * which, first check rows and then do an
407
- * exact cost comparison.
413
+ * which, first check rows and then do a fuzzy
414
+ * cost comparison with very small fuzz limit.
415
+ * (We used to do an exact cost comparison,
416
+ * but that results in annoying
417
+ * platform-specific plan variations due to
418
+ * roundoff in the cost estimates.) If things
419
+ * are still tied, arbitrarily keep only the
420
+ * old path. Notice that we will keep only
421
+ * the old path even if the less-fuzzy
422
+ * comparison decides the startup and total
423
+ * costs compare differently.
408
424
*/
409
425
if (new_path -> rows < old_path -> rows )
410
426
remove_old = true; /* new dominates old */
411
427
else if (new_path -> rows > old_path -> rows )
412
428
accept_new = false; /* old dominates new */
413
- else if (compare_path_costs (new_path , old_path ,
414
- TOTAL_COST ) < 0 )
429
+ else if (compare_path_costs_fuzzily (new_path , old_path ,
430
+ 1.0000000001 ) == COSTS_BETTER1 )
415
431
remove_old = true; /* new dominates old */
416
432
else
417
433
accept_new = false; /* old equals or dominates new */
0 commit comments