Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit732bfa2

Browse files
committed
Fix cost estimation for indexscan filter conditions.
cost_index's method for estimating per-tuple costs of evaluating filterconditions (a/k/a qpquals) was completely wrong in the presence of derivedindexable conditions, such as range conditions derived from a LIKE clause.This was largely masked in common cases as a result of all simple operatorclauses having about the same costs, but it could show up in a big way whendealing with functional indexes containing expensive functions, as seen forexample in bug #6579 from Istvan Endredy. Rejigger the calculation to givesane answers when the indexquals aren't a subset of the baserestrictinfolist. As a side benefit, we now do the calculation properly for casesinvolving join clauses (ie, parameterized indexscans), which we alwaysoverestimated before.There are still cases where this is an oversimplification, such as clausesthat can be dropped because they are implied by a partial index'spredicate. But we've never accounted for that in cost estimates before,and I'm not convinced it's worth the cycles to try to do so.
1 parent880bfc3 commit732bfa2

File tree

1 file changed

+21
-19
lines changed

1 file changed

+21
-19
lines changed

‎src/backend/optimizer/path/costsize.c

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ cost_index(IndexPath *path, PlannerInfo *root, double loop_count)
228228
IndexOptInfo*index=path->indexinfo;
229229
RelOptInfo*baserel=index->rel;
230230
boolindexonly= (path->path.pathtype==T_IndexOnlyScan);
231+
List*allclauses;
231232
Coststartup_cost=0;
232233
Costrun_cost=0;
233234
CostindexStartupCost;
@@ -239,6 +240,7 @@ cost_index(IndexPath *path, PlannerInfo *root, double loop_count)
239240
spc_random_page_cost;
240241
Costmin_IO_cost,
241242
max_IO_cost;
243+
QualCostqpqual_cost;
242244
Costcpu_per_tuple;
243245
doubletuples_fetched;
244246
doublepages_fetched;
@@ -267,8 +269,6 @@ cost_index(IndexPath *path, PlannerInfo *root, double loop_count)
267269
* Note that we force the clauses to be treated as non-join clauses
268270
* during selectivity estimation.
269271
*/
270-
List*allclauses;
271-
272272
allclauses=list_union_ptr(baserel->baserestrictinfo,
273273
path->indexclauses);
274274
path->path.rows=baserel->tuples*
@@ -283,6 +283,9 @@ cost_index(IndexPath *path, PlannerInfo *root, double loop_count)
283283
}
284284
else
285285
{
286+
/* allclauses should just be the rel's restriction clauses */
287+
allclauses=baserel->baserestrictinfo;
288+
286289
/*
287290
* The number of rows is the same as the parent rel's estimate, since
288291
* this isn't a parameterized path.
@@ -442,24 +445,23 @@ cost_index(IndexPath *path, PlannerInfo *root, double loop_count)
442445
/*
443446
* Estimate CPU costs per tuple.
444447
*
445-
* Normally the indexquals will be removed from the list of restriction
446-
* clauses that we have to evaluate as qpquals, so we should subtract
447-
* their costs from baserestrictcost. But if we are doing a join then
448-
* some of the indexquals are join clauses and shouldn't be subtracted.
449-
* Rather than work out exactly how much to subtract, we don't subtract
450-
* anything.
451-
*/
452-
startup_cost+=baserel->baserestrictcost.startup;
453-
cpu_per_tuple=cpu_tuple_cost+baserel->baserestrictcost.per_tuple;
454-
455-
if (path->path.required_outer==NULL)
456-
{
457-
QualCostindex_qual_cost;
448+
* What we want here is cpu_tuple_cost plus the evaluation costs of any
449+
* qual clauses that we have to evaluate as qpquals. We approximate that
450+
* list as allclauses minus any clauses appearing in indexquals (as
451+
* before, assuming that pointer equality is enough to recognize duplicate
452+
* RestrictInfos). This method neglects some considerations such as
453+
* clauses that needn't be checked because they are implied by a partial
454+
* index's predicate. It does not seem worth the cycles to try to factor
455+
* those things in at this stage, even though createplan.c will take pains
456+
* to remove such unnecessary clauses from the qpquals list if this path
457+
* is selected for use.
458+
*/
459+
cost_qual_eval(&qpqual_cost,
460+
list_difference_ptr(allclauses,path->indexquals),
461+
root);
458462

459-
cost_qual_eval(&index_qual_cost,path->indexquals,root);
460-
/* any startup cost still has to be paid ... */
461-
cpu_per_tuple-=index_qual_cost.per_tuple;
462-
}
463+
startup_cost+=qpqual_cost.startup;
464+
cpu_per_tuple=cpu_tuple_cost+qpqual_cost.per_tuple;
463465

464466
run_cost+=cpu_per_tuple*tuples_fetched;
465467

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp