@@ -7453,6 +7453,7 @@ gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
74537453 qual_arg_cost ,
74547454 spc_random_page_cost ,
74557455 outer_scans ;
7456+ Cost descentCost ;
74567457 Relation indexRel ;
74577458 GinStatsData ginStats ;
74587459 ListCell * lc ;
@@ -7677,6 +7678,47 @@ gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
76777678 */
76787679 dataPagesFetched = ceil (numDataPages * partialScale );
76797680
7681+ * indexStartupCost = 0 ;
7682+ * indexTotalCost = 0 ;
7683+
7684+ /*
7685+ * Add a CPU-cost component to represent the costs of initial entry btree
7686+ * descent. We don't charge any I/O cost for touching upper btree levels,
7687+ * since they tend to stay in cache, but we still have to do about log2(N)
7688+ * comparisons to descend a btree of N leaf tuples. We charge one
7689+ * cpu_operator_cost per comparison.
7690+ *
7691+ * If there are ScalarArrayOpExprs, charge this once per SA scan. The
7692+ * ones after the first one are not startup cost so far as the overall
7693+ * plan is concerned, so add them only to "total" cost.
7694+ */
7695+ if (numEntries > 1 ) /* avoid computing log(0) */
7696+ {
7697+ descentCost = ceil (log (numEntries ) / log (2.0 )) * cpu_operator_cost ;
7698+ * indexStartupCost += descentCost * counts .searchEntries ;
7699+ * indexTotalCost += counts .arrayScans * descentCost * counts .searchEntries ;
7700+ }
7701+
7702+ /*
7703+ * Add a cpu cost per entry-page fetched. This is not amortized over a
7704+ * loop.
7705+ */
7706+ * indexStartupCost += entryPagesFetched * DEFAULT_PAGE_CPU_MULTIPLIER * cpu_operator_cost ;
7707+ * indexTotalCost += entryPagesFetched * counts .arrayScans * DEFAULT_PAGE_CPU_MULTIPLIER * cpu_operator_cost ;
7708+
7709+ /*
7710+ * Add a cpu cost per data-page fetched. This is also not amortized over a
7711+ * loop. Since those are the data pages from the partial match algorithm,
7712+ * charge them as startup cost.
7713+ */
7714+ * indexStartupCost += DEFAULT_PAGE_CPU_MULTIPLIER * cpu_operator_cost * dataPagesFetched ;
7715+
7716+ /*
7717+ * Since we add the startup cost to the total cost later on, remove the
7718+ * initial arrayscan from the total.
7719+ */
7720+ * indexTotalCost += dataPagesFetched * (counts .arrayScans - 1 ) * DEFAULT_PAGE_CPU_MULTIPLIER * cpu_operator_cost ;
7721+
76807722 /*
76817723 * Calculate cache effects if more than one scan due to nestloops or array
76827724 * quals. The result is pro-rated per nestloop scan, but the array qual
@@ -7700,7 +7742,7 @@ gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
77007742 * Here we use random page cost because logically-close pages could be far
77017743 * apart on disk.
77027744 */
7703- * indexStartupCost = (entryPagesFetched + dataPagesFetched ) * spc_random_page_cost ;
7745+ * indexStartupCost + = (entryPagesFetched + dataPagesFetched ) * spc_random_page_cost ;
77047746
77057747 /*
77067748 * Now compute the number of data pages fetched during the scan.
@@ -7728,6 +7770,15 @@ gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
77287770 if (dataPagesFetchedBySel > dataPagesFetched )
77297771 dataPagesFetched = dataPagesFetchedBySel ;
77307772
7773+ /* Add one page cpu-cost to the startup cost */
7774+ * indexStartupCost += DEFAULT_PAGE_CPU_MULTIPLIER * cpu_operator_cost * counts .searchEntries ;
7775+
7776+ /*
7777+ * Add once again a CPU-cost for those data pages, before amortizing for
7778+ * cache.
7779+ */
7780+ * indexTotalCost += dataPagesFetched * counts .arrayScans * DEFAULT_PAGE_CPU_MULTIPLIER * cpu_operator_cost ;
7781+
77317782 /* Account for cache effects, the same as above */
77327783 if (outer_scans > 1 || counts .arrayScans > 1 )
77337784 {
@@ -7739,19 +7790,27 @@ gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
77397790 }
77407791
77417792 /* And apply random_page_cost as the cost per page */
7742- * indexTotalCost = * indexStartupCost +
7793+ * indexTotalCost + = * indexStartupCost +
77437794 dataPagesFetched * spc_random_page_cost ;
77447795
77457796 /*
7746- * Add on index qual eval costs, much as in genericcostestimate. But we
7747- * can disregard indexorderbys, since GIN doesn't support those.
7797+ * Add on index qual eval costs, much as in genericcostestimate. We charge
7798+ * cpu but we can disregard indexorderbys, since GIN doesn't support
7799+ * those.
77487800 */
77497801 qual_arg_cost = index_other_operands_eval_cost (root , indexQuals );
77507802 qual_op_cost = cpu_operator_cost * list_length (indexQuals );
77517803
77527804 * indexStartupCost += qual_arg_cost ;
77537805 * indexTotalCost += qual_arg_cost ;
7754- * indexTotalCost += (numTuples * * indexSelectivity ) * (cpu_index_tuple_cost + qual_op_cost );
7806+
7807+ /*
7808+ * Add a cpu cost per search entry, corresponding to the actual visited
7809+ * entries.
7810+ */
7811+ * indexTotalCost += (counts .searchEntries * counts .arrayScans ) * (qual_op_cost );
7812+ /* Now add a cpu cost per tuple in the posting lists / trees */
7813+ * indexTotalCost += (numTuples * * indexSelectivity ) * (cpu_index_tuple_cost );
77557814 * indexPages = dataPagesFetched ;
77567815}
77577816
0 commit comments