Tweak genericcostestimate's fudge factor for index size.
authorTom Lane <[email protected]>
Wed, 24 Oct 2012 20:25:40 +0000 (16:25 -0400)
committerTom Lane <[email protected]>
Wed, 24 Oct 2012 20:25:40 +0000 (16:25 -0400)
To provide some bias against using a large index when a small one would do
as well, genericcostestimate adds a "fudge factor", which for a long time
was random_page_cost * index_pages/10000.  However, this can grow to be the
dominant term in indexscan cost estimates when the index involved is large
enough, a behavior that was never intended.  Change to a ln(1 + n/10000)
formulation, which has nearly the same behavior up to a few hundred pages
but tails off significantly thereafter.  (A log curve seems correct on
first principles, since what we're trying to account for here is index
descent costs, which are typically logarithmic.)  Per bug #7619 from Niko
Kiirala.

Possibly this change should get back-patched, but I'm hesitant to mess with
cost estimates in stable branches.

src/backend/utils/adt/selfuncs.c

index 61100aec4aedd89742abe27e5b19188e3eb02d74..60000aaf347411e01dd72e448318d94d79404b16 100644 (file)
@@ -6130,12 +6130,14 @@ genericcostestimate(PlannerInfo *root,
         * index would have better selectivity.)
         *
         * We can deal with this by adding a very small "fudge factor" that
-        * depends on the index size.  The fudge factor used here is one
-        * spc_random_page_cost per 10000 index pages, which should be small
-        * enough to not alter index-vs-seqscan decisions, but will prevent
-        * indexes of different sizes from looking exactly equally attractive.
+        * depends on the index size, so that indexes of different sizes won't
+        * look exactly equally attractive.  To ensure the fudge factor stays
+        * small even for very large indexes, use a log function.  (We previously
+        * used a factor of one spc_random_page_cost per 10000 index pages, which
+        * grew too large for large indexes.  This expression has about the same
+        * growth rate for small indexes, but tails off quickly.)
         */
-       *indexTotalCost += index->pages * spc_random_page_cost / 10000.0;
+       *indexTotalCost += log(1.0 + index->pages / 10000.0) * spc_random_page_cost;
 
        /*
         * CPU cost: any complex expressions in the indexquals will need to be