Refactor bitmap heap scan estimation of heap pages fetched.
authorRobert Haas <rhaas@postgresql.org>
Fri, 27 Jan 2017 21:22:11 +0000 (16:22 -0500)
committerRobert Haas <rhaas@postgresql.org>
Fri, 27 Jan 2017 21:28:47 +0000 (16:28 -0500)
Currently, we only need this logic in order to cost a Bitmap Heap
Scan.  But a pending patch for Parallel Bitmap Heap Scan also uses
it to help figure out how many workers to use for the scan, which
has to be determined prior to costing.  So, move the logic to
a separate function to make that easier.

Dilip Kumar.  The patch series of which this is a part has been
reviewed by Andres Freund, Amit Khendekar, Tushar Ahuja, Rafia
Sabih, Haribabu Kommi, and me; it is not clear from the email
discussion which of those people have looked specifically at this
part.

Discussion: http://postgr.es/m/CAFiTN-v3QYNJEZnnmKCeATuLbN-h9tMVfeEF0+BrouYDqjXgwg@mail.gmail.com

src/backend/optimizer/path/costsize.c
src/include/optimizer/cost.h

index 458f139d7cdcda7cfcbd407bfecc9ca2dd866c05..a43daa744c7c1d2ae7560dea42f5334b89f5b204 100644 (file)
@@ -813,7 +813,6 @@ cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel,
    Cost        startup_cost = 0;
    Cost        run_cost = 0;
    Cost        indexTotalCost;
-   Selectivity indexSelectivity;
    QualCost    qpqual_cost;
    Cost        cpu_per_tuple;
    Cost        cost_per_page;
@@ -837,54 +836,18 @@ cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel,
    if (!enable_bitmapscan)
        startup_cost += disable_cost;
 
-   /*
-    * Fetch total cost of obtaining the bitmap, as well as its total
-    * selectivity.
-    */
-   cost_bitmap_tree_node(bitmapqual, &indexTotalCost, &indexSelectivity);
+   pages_fetched = compute_bitmap_pages(root, baserel, bitmapqual,
+                                        loop_count, &indexTotalCost,
+                                        &tuples_fetched);
 
    startup_cost += indexTotalCost;
+   T = (baserel->pages > 1) ? (double) baserel->pages : 1.0;
 
    /* Fetch estimated page costs for tablespace containing table. */
    get_tablespace_page_costs(baserel->reltablespace,
                              &spc_random_page_cost,
                              &spc_seq_page_cost);
 
-   /*
-    * Estimate number of main-table pages fetched.
-    */
-   tuples_fetched = clamp_row_est(indexSelectivity * baserel->tuples);
-
-   T = (baserel->pages > 1) ? (double) baserel->pages : 1.0;
-
-   if (loop_count > 1)
-   {
-       /*
-        * For repeated bitmap scans, scale up the number of tuples fetched in
-        * the Mackert and Lohman formula by the number of scans, so that we
-        * estimate the number of pages fetched by all the scans. Then
-        * pro-rate for one scan.
-        */
-       pages_fetched = index_pages_fetched(tuples_fetched * loop_count,
-                                           baserel->pages,
-                                           get_indexpath_pages(bitmapqual),
-                                           root);
-       pages_fetched /= loop_count;
-   }
-   else
-   {
-       /*
-        * For a single scan, the number of heap pages that need to be fetched
-        * is the same as the Mackert and Lohman formula for the case T <= b
-        * (ie, no re-reads needed).
-        */
-       pages_fetched = (2.0 * T * tuples_fetched) / (2.0 * T + tuples_fetched);
-   }
-   if (pages_fetched >= T)
-       pages_fetched = T;
-   else
-       pages_fetched = ceil(pages_fetched);
-
    /*
     * For small numbers of pages we should charge spc_random_page_cost
     * apiece, while if nearly all the table's pages are being read, it's more
@@ -4820,3 +4783,69 @@ get_parallel_divisor(Path *path)
 
    return parallel_divisor;
 }
+
+/*
+ * compute_bitmap_pages
+ *
+ * compute number of pages fetched from heap in bitmap heap scan.
+ */
+double
+compute_bitmap_pages(PlannerInfo *root, RelOptInfo *baserel, Path *bitmapqual,
+                    int loop_count, Cost *cost, double *tuple)
+{
+   Cost        indexTotalCost;
+   Selectivity indexSelectivity;
+   double      T;
+   double      pages_fetched;
+   double      tuples_fetched;
+
+   /*
+    * Fetch total cost of obtaining the bitmap, as well as its total
+    * selectivity.
+    */
+   cost_bitmap_tree_node(bitmapqual, &indexTotalCost, &indexSelectivity);
+
+   /*
+    * Estimate number of main-table pages fetched.
+    */
+   tuples_fetched = clamp_row_est(indexSelectivity * baserel->tuples);
+
+   T = (baserel->pages > 1) ? (double) baserel->pages : 1.0;
+
+   if (loop_count > 1)
+   {
+       /*
+        * For repeated bitmap scans, scale up the number of tuples fetched in
+        * the Mackert and Lohman formula by the number of scans, so that we
+        * estimate the number of pages fetched by all the scans. Then
+        * pro-rate for one scan.
+        */
+       pages_fetched = index_pages_fetched(tuples_fetched * loop_count,
+                                           baserel->pages,
+                                           get_indexpath_pages(bitmapqual),
+                                           root);
+       pages_fetched /= loop_count;
+   }
+   else
+   {
+       /*
+        * For a single scan, the number of heap pages that need to be fetched
+        * is the same as the Mackert and Lohman formula for the case T <= b
+        * (ie, no re-reads needed).
+        */
+       pages_fetched =
+           (2.0 * T * tuples_fetched) / (2.0 * T + tuples_fetched);
+   }
+
+   if (pages_fetched >= T)
+       pages_fetched = T;
+   else
+       pages_fetched = ceil(pages_fetched);
+
+   if (cost)
+       *cost = indexTotalCost;
+   if (tuple)
+       *tuple = tuples_fetched;
+
+   return pages_fetched;
+}
index 39376ec10cfd127b2177015ec0c2de06ba684b7e..0e68264a41f1d0ab9596681022a14d206642a8ad 100644 (file)
@@ -183,6 +183,8 @@ extern void set_cte_size_estimates(PlannerInfo *root, RelOptInfo *rel,
                       double cte_rows);
 extern void set_foreign_size_estimates(PlannerInfo *root, RelOptInfo *rel);
 extern PathTarget *set_pathtarget_cost_width(PlannerInfo *root, PathTarget *target);
+extern double compute_bitmap_pages(PlannerInfo *root, RelOptInfo *baserel,
+                 Path *bitmapqual, int loop_count, Cost *cost, double *tuple);
 
 /*
  * prototypes for clausesel.c