]> granicus.if.org Git - postgresql/commitdiff
Refactor bitmap heap scan in preparation for parallel support.
authorRobert Haas <rhaas@postgresql.org>
Thu, 2 Mar 2017 13:17:40 +0000 (18:47 +0530)
committerRobert Haas <rhaas@postgresql.org>
Thu, 2 Mar 2017 13:17:40 +0000 (18:47 +0530)
The final patch will be less messy if the prefetching support is
a bit better isolated, so do that.

Dilip Kumar, with some changes by me.  The larger patch set of which
this is a part has been reviewed and tested by (at least) Andres
Freund, Amit Khandekar, Tushar Ahuja, Rafia Sabih, Haribabu Kommi, and
Thomas Munro.

src/backend/executor/nodeBitmapHeapscan.c

index c871aa0348287e1d4466e13f9024269ab9bfa209..c1aa9f13bdf5b3df609ddef3138f34c532762e87 100644 (file)
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static void bitgetpage(HeapScanDesc scan, TBMIterateResult *tbmres);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
+                                                        TBMIterateResult *tbmres);
+static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
+static inline void BitmapPrefetch(BitmapHeapScanState *node,
+                          HeapScanDesc scan);
 
 
 /* ----------------------------------------------------------------
@@ -69,10 +74,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
        TIDBitmap  *tbm;
        TBMIterator *tbmiterator;
        TBMIterateResult *tbmres;
-
-#ifdef USE_PREFETCH
-       TBMIterator *prefetch_iterator;
-#endif
        OffsetNumber targoffset;
        TupleTableSlot *slot;
 
@@ -85,9 +86,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
        tbm = node->tbm;
        tbmiterator = node->tbmiterator;
        tbmres = node->tbmres;
-#ifdef USE_PREFETCH
-       prefetch_iterator = node->prefetch_iterator;
-#endif
 
        /*
         * If we haven't yet performed the underlying index scan, do it, and begin
@@ -115,7 +113,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 #ifdef USE_PREFETCH
                if (node->prefetch_maximum > 0)
                {
-                       node->prefetch_iterator = prefetch_iterator = tbm_begin_iterate(tbm);
+                       node->prefetch_iterator = tbm_begin_iterate(tbm);
                        node->prefetch_pages = 0;
                        node->prefetch_target = -1;
                }
@@ -139,21 +137,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
                                break;
                        }
 
-#ifdef USE_PREFETCH
-                       if (node->prefetch_pages > 0)
-                       {
-                               /* The main iterator has closed the distance by one page */
-                               node->prefetch_pages--;
-                       }
-                       else if (prefetch_iterator)
-                       {
-                               /* Do not let the prefetch iterator get behind the main one */
-                               TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-                               if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
-                                       elog(ERROR, "prefetch and main iterators are out of sync");
-                       }
-#endif   /* USE_PREFETCH */
+                       BitmapAdjustPrefetchIterator(node, tbmres);
 
                        /*
                         * Ignore any claimed entries past what we think is the end of the
@@ -182,23 +166,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
                         */
                        scan->rs_cindex = 0;
 
-#ifdef USE_PREFETCH
-
-                       /*
-                        * Increase prefetch target if it's not yet at the max.  Note that
-                        * we will increase it to zero after fetching the very first
-                        * page/tuple, then to one after the second tuple is fetched, then
-                        * it doubles as later pages are fetched.
-                        */
-                       if (node->prefetch_target >= node->prefetch_maximum)
-                                /* don't increase any further */ ;
-                       else if (node->prefetch_target >= node->prefetch_maximum / 2)
-                               node->prefetch_target = node->prefetch_maximum;
-                       else if (node->prefetch_target > 0)
-                               node->prefetch_target *= 2;
-                       else
-                               node->prefetch_target++;
-#endif   /* USE_PREFETCH */
+                       /* Adjust the prefetch target */
+                       BitmapAdjustPrefetchTarget(node);
                }
                else
                {
@@ -227,8 +196,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
                        continue;
                }
 
-#ifdef USE_PREFETCH
-
                /*
                 * We issue prefetch requests *after* fetching the current page to try
                 * to avoid having prefetching interfere with the main I/O. Also, this
@@ -236,24 +203,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
                 * to do on the current page, else we may uselessly prefetch the same
                 * page we are just about to request for real.
                 */
-               if (prefetch_iterator)
-               {
-                       while (node->prefetch_pages < node->prefetch_target)
-                       {
-                               TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-                               if (tbmpre == NULL)
-                               {
-                                       /* No more pages to prefetch */
-                                       tbm_end_iterate(prefetch_iterator);
-                                       node->prefetch_iterator = prefetch_iterator = NULL;
-                                       break;
-                               }
-                               node->prefetch_pages++;
-                               PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
-                       }
-               }
-#endif   /* USE_PREFETCH */
+               BitmapPrefetch(node, scan);
 
                /*
                 * Okay to fetch the tuple
@@ -411,6 +361,84 @@ bitgetpage(HeapScanDesc scan, TBMIterateResult *tbmres)
        scan->rs_ntuples = ntup;
 }
 
+/*
+ *     BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ */
+static inline void
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
+                                                        TBMIterateResult *tbmres)
+{
+#ifdef USE_PREFETCH
+       TBMIterator *prefetch_iterator = node->prefetch_iterator;
+
+       if (node->prefetch_pages > 0)
+       {
+               /* The main iterator has closed the distance by one page */
+               node->prefetch_pages--;
+       }
+       else if (prefetch_iterator)
+       {
+               /* Do not let the prefetch iterator get behind the main one */
+               TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+
+               if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
+                       elog(ERROR, "prefetch and main iterators are out of sync");
+       }
+#endif   /* USE_PREFETCH */
+}
+
+/*
+ * BitmapAdjustPrefetchTarget - Adjust the prefetch target
+ *
+ * Increase prefetch target if it's not yet at the max.  Note that
+ * we will increase it to zero after fetching the very first
+ * page/tuple, then to one after the second tuple is fetched, then
+ * it doubles as later pages are fetched.
+ */
+static inline void
+BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
+{
+#ifdef USE_PREFETCH
+       if (node->prefetch_target >= node->prefetch_maximum)
+                /* don't increase any further */ ;
+       else if (node->prefetch_target >= node->prefetch_maximum / 2)
+               node->prefetch_target = node->prefetch_maximum;
+       else if (node->prefetch_target > 0)
+               node->prefetch_target *= 2;
+       else
+               node->prefetch_target++;
+#endif   /* USE_PREFETCH */
+}
+
+/*
+ * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
+ */
+static inline void
+BitmapPrefetch(BitmapHeapScanState *node, HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+       TBMIterator *prefetch_iterator = node->prefetch_iterator;
+
+       if (prefetch_iterator)
+       {
+               while (node->prefetch_pages < node->prefetch_target)
+               {
+                       TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+
+                       if (tbmpre == NULL)
+                       {
+                               /* No more pages to prefetch */
+                               tbm_end_iterate(prefetch_iterator);
+                               node->prefetch_iterator = NULL;
+                               break;
+                       }
+                       node->prefetch_pages++;
+                       PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+               }
+       }
+#endif   /* USE_PREFETCH */
+}
+
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */