]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Secondary refactor of heap scanning functions
authorDavid Rowley <drowley@postgresql.org>
Thu, 4 Apr 2024 06:22:45 +0000 (19:22 +1300)
committerDavid Rowley <drowley@postgresql.org>
Thu, 4 Apr 2024 06:22:45 +0000 (19:22 +1300)
Similar to 44086b097, refactor heap scanning functions to be more
suitable for the read stream API.

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_YtXJiYKQvb5JsA2SkwrsizYLugs4sSOZh3EAjKUg=gEQ@mail.gmail.com

src/backend/access/heap/heapam.c
src/backend/access/heap/heapam_handler.c

index 7906d5d7c5bd29001cc14392bb604ecd0cd05b33..dada2ecd1e32ab6a15a27b98ae70fb4788aa32aa 100644 (file)
@@ -83,6 +83,11 @@ static Bitmapset *HeapDetermineColumnsInfo(Relation relation,
 static bool heap_acquire_tuplock(Relation relation, ItemPointer tid,
                                                                 LockTupleMode mode, LockWaitPolicy wait_policy,
                                                                 bool *have_tuple_lock);
+static inline BlockNumber heapgettup_advance_block(HeapScanDesc scan,
+                                                                                                  BlockNumber block,
+                                                                                                  ScanDirection dir);
+static pg_noinline BlockNumber heapgettup_initial_block(HeapScanDesc scan,
+                                                                                                               ScanDirection dir);
 static void compute_new_xmax_infomask(TransactionId xmax, uint16 old_infomask,
                                                                          uint16 old_infomask2, TransactionId add_to_xmax,
                                                                          LockTupleMode mode, bool is_update,
@@ -455,16 +460,14 @@ heap_prepare_pagescan(TableScanDesc sscan)
 }
 
 /*
- * heapfetchbuf - read and pin the given MAIN_FORKNUM block number.
+ * heap_fetch_next_buffer - read and pin the next block from MAIN_FORKNUM.
  *
- * Read the specified block of the scan relation into a buffer and pin that
- * buffer before saving it in the scan descriptor.
+ * Read the next block of the scan relation into a buffer and pin that buffer
+ * before saving it in the scan descriptor.
  */
 static inline void
-heapfetchbuf(HeapScanDesc scan, BlockNumber block)
+heap_fetch_next_buffer(HeapScanDesc scan, ScanDirection dir)
 {
-       Assert(block < scan->rs_nblocks);
-
        /* release previous scan buffer, if any */
        if (BufferIsValid(scan->rs_cbuf))
        {
@@ -479,10 +482,25 @@ heapfetchbuf(HeapScanDesc scan, BlockNumber block)
         */
        CHECK_FOR_INTERRUPTS();
 
-       /* read page using selected strategy */
-       scan->rs_cbuf = ReadBufferExtended(scan->rs_base.rs_rd, MAIN_FORKNUM, block,
-                                                                          RBM_NORMAL, scan->rs_strategy);
-       scan->rs_cblock = block;
+       if (unlikely(!scan->rs_inited))
+       {
+               scan->rs_cblock = heapgettup_initial_block(scan, dir);
+
+               /* ensure rs_cbuf is invalid when we get InvalidBlockNumber */
+               Assert(scan->rs_cblock != InvalidBlockNumber ||
+                          !BufferIsValid(scan->rs_cbuf));
+
+               scan->rs_inited = true;
+       }
+       else
+               scan->rs_cblock = heapgettup_advance_block(scan, scan->rs_cblock,
+                                                                                                  dir);
+
+       /* read block if valid */
+       if (BlockNumberIsValid(scan->rs_cblock))
+               scan->rs_cbuf = ReadBufferExtended(scan->rs_base.rs_rd, MAIN_FORKNUM,
+                                                                                  scan->rs_cblock, RBM_NORMAL,
+                                                                                  scan->rs_strategy);
 }
 
 /*
@@ -492,7 +510,7 @@ heapfetchbuf(HeapScanDesc scan, BlockNumber block)
  * occur with empty tables and in parallel scans when parallel workers get all
  * of the pages before we can get a chance to get our first page.
  */
-static BlockNumber
+static pg_noinline BlockNumber
 heapgettup_initial_block(HeapScanDesc scan, ScanDirection dir)
 {
        Assert(!scan->rs_inited);
@@ -619,7 +637,7 @@ heapgettup_continue_page(HeapScanDesc scan, ScanDirection dir, int *linesleft,
 }
 
 /*
- * heapgettup_advance_block - helper for heapgettup() and heapgettup_pagemode()
+ * heapgettup_advance_block - helper for heap_fetch_next_buffer()
  *
  * Given the current block number, the scan direction, and various information
  * contained in the scan descriptor, calculate the BlockNumber to scan next
@@ -730,23 +748,13 @@ heapgettup(HeapScanDesc scan,
                   ScanKey key)
 {
        HeapTuple       tuple = &(scan->rs_ctup);
-       BlockNumber block;
        Page            page;
        OffsetNumber lineoff;
        int                     linesleft;
 
-       if (unlikely(!scan->rs_inited))
-       {
-               block = heapgettup_initial_block(scan, dir);
-               /* ensure rs_cbuf is invalid when we get InvalidBlockNumber */
-               Assert(block != InvalidBlockNumber || !BufferIsValid(scan->rs_cbuf));
-               scan->rs_inited = true;
-       }
-       else
+       if (likely(scan->rs_inited))
        {
                /* continue from previously returned page/tuple */
-               block = scan->rs_cblock;
-
                LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
                page = heapgettup_continue_page(scan, dir, &linesleft, &lineoff);
                goto continue_page;
@@ -756,9 +764,16 @@ heapgettup(HeapScanDesc scan,
         * advance the scan until we find a qualifying tuple or run out of stuff
         * to scan
         */
-       while (block != InvalidBlockNumber)
+       while (true)
        {
-               heapfetchbuf(scan, block);
+               heap_fetch_next_buffer(scan, dir);
+
+               /* did we run out of blocks to scan? */
+               if (!BufferIsValid(scan->rs_cbuf))
+                       break;
+
+               Assert(BufferGetBlockNumber(scan->rs_cbuf) == scan->rs_cblock);
+
                LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
                page = heapgettup_start_page(scan, dir, &linesleft, &lineoff);
 continue_page:
@@ -780,7 +795,7 @@ continue_page:
 
                        tuple->t_data = (HeapTupleHeader) PageGetItem(page, lpp);
                        tuple->t_len = ItemIdGetLength(lpp);
-                       ItemPointerSet(&(tuple->t_self), block, lineoff);
+                       ItemPointerSet(&(tuple->t_self), scan->rs_cblock, lineoff);
 
                        visible = HeapTupleSatisfiesVisibility(tuple,
                                                                                                   scan->rs_base.rs_snapshot,
@@ -810,9 +825,6 @@ continue_page:
                 * it's time to move to the next.
                 */
                LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
-
-               /* get the BlockNumber to scan next */
-               block = heapgettup_advance_block(scan, block, dir);
        }
 
        /* end of scan */
@@ -832,9 +844,9 @@ continue_page:
  *
  * The internal logic is much the same as heapgettup's too, but there are some
  * differences: we do not take the buffer content lock (that only needs to
- * happen inside heapgetpage), and we iterate through just the tuples listed
- * in rs_vistuples[] rather than all tuples on the page.  Notice that
- * lineindex is 0-based, where the corresponding loop variable lineoff in
+ * happen inside heap_prepare_pagescan), and we iterate through just the
+ * tuples listed in rs_vistuples[] rather than all tuples on the page.  Notice
+ * that lineindex is 0-based, where the corresponding loop variable lineoff in
  * heapgettup is 1-based.
  * ----------------
  */
@@ -845,22 +857,13 @@ heapgettup_pagemode(HeapScanDesc scan,
                                        ScanKey key)
 {
        HeapTuple       tuple = &(scan->rs_ctup);
-       BlockNumber block;
        Page            page;
        int                     lineindex;
        int                     linesleft;
 
-       if (unlikely(!scan->rs_inited))
-       {
-               block = heapgettup_initial_block(scan, dir);
-               /* ensure rs_cbuf is invalid when we get InvalidBlockNumber */
-               Assert(block != InvalidBlockNumber || !BufferIsValid(scan->rs_cbuf));
-               scan->rs_inited = true;
-       }
-       else
+       if (likely(scan->rs_inited))
        {
                /* continue from previously returned page/tuple */
-               block = scan->rs_cblock;        /* current page */
                page = BufferGetPage(scan->rs_cbuf);
 
                lineindex = scan->rs_cindex + dir;
@@ -877,10 +880,15 @@ heapgettup_pagemode(HeapScanDesc scan,
         * advance the scan until we find a qualifying tuple or run out of stuff
         * to scan
         */
-       while (block != InvalidBlockNumber)
+       while (true)
        {
-               /* read the page */
-               heapfetchbuf(scan, block);
+               heap_fetch_next_buffer(scan, dir);
+
+               /* did we run out of blocks to scan? */
+               if (!BufferIsValid(scan->rs_cbuf))
+                       break;
+
+               Assert(BufferGetBlockNumber(scan->rs_cbuf) == scan->rs_cblock);
 
                /* prune the page and determine visible tuple offsets */
                heap_prepare_pagescan((TableScanDesc) scan);
@@ -902,7 +910,7 @@ continue_page:
 
                        tuple->t_data = (HeapTupleHeader) PageGetItem(page, lpp);
                        tuple->t_len = ItemIdGetLength(lpp);
-                       ItemPointerSet(&(tuple->t_self), block, lineoff);
+                       ItemPointerSet(&(tuple->t_self), scan->rs_cblock, lineoff);
 
                        /* skip any tuples that don't match the scan key */
                        if (key != NULL &&
@@ -913,9 +921,6 @@ continue_page:
                        scan->rs_cindex = lineindex;
                        return;
                }
-
-               /* get the BlockNumber to scan next */
-               block = heapgettup_advance_block(scan, block, dir);
        }
 
        /* end of scan */
index db99d2fcfa75649ae311df978155604995615ad2..3e7a6b5548b05882414192f4431fe30b3b267b0d 100644 (file)
@@ -2489,7 +2489,7 @@ heapam_scan_sample_next_tuple(TableScanDesc scan, SampleScanState *scanstate,
                                visible = SampleHeapTupleVisible(scan, hscan->rs_cbuf,
                                                                                                 tuple, tupoffset);
 
-                       /* in pagemode, heapgetpage did this for us */
+                       /* in pagemode, heap_prepare_pagescan did this for us */
                        if (!pagemode)
                                HeapCheckForSerializableConflictOut(visible, scan->rs_rd, tuple,
                                                                                                        hscan->rs_cbuf, scan->rs_snapshot);