@@ -7453,6 +7453,7 @@ gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
7453
7453
qual_arg_cost ,
7454
7454
spc_random_page_cost ,
7455
7455
outer_scans ;
7456
+ Cost descentCost ;
7456
7457
Relation indexRel ;
7457
7458
GinStatsData ginStats ;
7458
7459
ListCell * lc ;
@@ -7677,6 +7678,47 @@ gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
7677
7678
*/
7678
7679
dataPagesFetched = ceil (numDataPages * partialScale );
7679
7680
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
+
7680
7722
/*
7681
7723
* Calculate cache effects if more than one scan due to nestloops or array
7682
7724
* 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,
7700
7742
* Here we use random page cost because logically-close pages could be far
7701
7743
* apart on disk.
7702
7744
*/
7703
- * indexStartupCost = (entryPagesFetched + dataPagesFetched ) * spc_random_page_cost ;
7745
+ * indexStartupCost + = (entryPagesFetched + dataPagesFetched ) * spc_random_page_cost ;
7704
7746
7705
7747
/*
7706
7748
* Now compute the number of data pages fetched during the scan.
@@ -7728,6 +7770,15 @@ gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
7728
7770
if (dataPagesFetchedBySel > dataPagesFetched )
7729
7771
dataPagesFetched = dataPagesFetchedBySel ;
7730
7772
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
+
7731
7782
/* Account for cache effects, the same as above */
7732
7783
if (outer_scans > 1 || counts .arrayScans > 1 )
7733
7784
{
@@ -7739,19 +7790,27 @@ gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
7739
7790
}
7740
7791
7741
7792
/* And apply random_page_cost as the cost per page */
7742
- * indexTotalCost = * indexStartupCost +
7793
+ * indexTotalCost + = * indexStartupCost +
7743
7794
dataPagesFetched * spc_random_page_cost ;
7744
7795
7745
7796
/*
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.
7748
7800
*/
7749
7801
qual_arg_cost = index_other_operands_eval_cost (root , indexQuals );
7750
7802
qual_op_cost = cpu_operator_cost * list_length (indexQuals );
7751
7803
7752
7804
* indexStartupCost += qual_arg_cost ;
7753
7805
* 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 );
7755
7814
* indexPages = dataPagesFetched ;
7756
7815
}
7757
7816
0 commit comments