diff --git a/doc/src/sgml/indexam.sgml b/doc/src/sgml/indexam.sgml index e03ebc9..de5b825 100644 --- a/doc/src/sgml/indexam.sgml +++ b/doc/src/sgml/indexam.sgml @@ -1104,19 +1104,44 @@ amcostestimate (PlannerInfo *root, - Compute the index access cost. A generic estimator might do this: + Compute the index access cost. A generic estimator might compute this as + the disk access cost plus the CPU cost. + The disk access cost might be estimated: /* - * Our generic assumption is that the index pages will be read - * sequentially, so they cost seq_page_cost each, not random_page_cost. - * Also, we charge for evaluation of the indexquals at each index row. - * All the costs are assumed to be paid incrementally during the scan. + * For a single index scan, we just charge spc_random_page_cost per + * page touched. */ -cost_qual_eval(&index_qual_cost, path->indexquals, root); -*indexStartupCost = index_qual_cost.startup; -*indexTotalCost = seq_page_cost * numIndexPages + - (cpu_index_tuple_cost + index_qual_cost.per_tuple) * numIndexTuples; +*indexTotalCost = numIndexPages * spc_random_page_cost; + + + The CPU cost might be estimated: + + +/* + * CPU cost: any complex expressions in the indexquals will need to be + * evaluated once at the start of the scan to reduce them to runtime keys + * to pass to the index AM (see nodeIndexscan.c). We model the per-tuple + * CPU costs as cpu_index_tuple_cost plus one cpu_operator_cost per + * indexqual operator. Because we have numIndexTuples as a per-scan + * number, we have to multiply by num_sa_scans to get the correct result + * for ScalarArrayOpExpr cases. Similarly add in costs for any index + * ORDER BY expressions. + */ +cost_qual_eval(&index_qual_cost, indexQuals, root); +qual_arg_cost = index_qual_cost.startup + index_qual_cost.per_tuple; +cost_qual_eval(&index_qual_cost, indexOrderBys, root); +qual_arg_cost += index_qual_cost.startup + index_qual_cost.per_tuple; +qual_op_cost = cpu_operator_cost * + (list_length(indexQuals) + list_length(indexOrderBys)); +qual_arg_cost -= qual_op_cost; +if (qual_arg_cost < 0) /* just in case... */ + qual_arg_cost = 0; + +*indexStartupCost = qual_arg_cost; +*indexTotalCost += qual_arg_cost; +*indexTotalCost += numIndexTuples * num_sa_scans * (cpu_index_tuple_cost + qual_op_cost); However, the above does not account for amortization of index reads