Move EXPLAIN counter increment to heapam_scan_bitmap_next_block
authorMelanie Plageman <melanieplageman@gmail.com>
Fri, 25 Oct 2024 14:11:46 +0000 (10:11 -0400)
committerMelanie Plageman <melanieplageman@gmail.com>
Fri, 25 Oct 2024 14:11:46 +0000 (10:11 -0400)
Increment the lossy and exact page counters for EXPLAIN of bitmap heap
scans in heapam_scan_bitmap_next_block(). Note that other table AMs will
need to do this as well

Pushing the counters into heapam_scan_bitmap_next_block() is required to
be able to use the read stream API for bitmap heap scans. The bitmap
iterator must be advanced from inside the read stream callback, so
TBMIterateResults cannot be used as a flow control mechanism in
BitmapHeapNext().

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Heikki Linnakangas
Discussion: https://postgr.es/m/063e4eb4-32d9-439e-a0b1-75565a9835a8%40iki.fi

src/backend/access/heap/heapam_handler.c
src/backend/executor/nodeBitmapHeapscan.c
src/include/access/tableam.h

index 8c59b77b64f14fe19bbde9f77d96a4590c9410c6..166aab7a93ca7418b2c3c5ad55121a31dcf01e04 100644 (file)
@@ -2115,7 +2115,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-                             TBMIterateResult *tbmres)
+                             TBMIterateResult *tbmres,
+                             uint64 *lossy_pages, uint64 *exact_pages)
 {
    HeapScanDesc hscan = (HeapScanDesc) scan;
    BlockNumber block = tbmres->blockno;
@@ -2243,6 +2244,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
    Assert(ntup <= MaxHeapTuplesPerPage);
    hscan->rs_ntuples = ntup;
 
+   if (tbmres->ntuples >= 0)
+       (*exact_pages)++;
+   else
+       (*lossy_pages)++;
+
    return ntup > 0;
 }
 
index 3c63bdd93dff394915abc97e581923c18896927e..f4690a20bb1f7c33f4c2d374c0215ce0348a40ec 100644 (file)
@@ -212,8 +212,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
    for (;;)
    {
-       bool        valid_block;
-
        CHECK_FOR_INTERRUPTS();
 
        /*
@@ -233,14 +231,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
            BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-           valid_block = table_scan_bitmap_next_block(scan, tbmres);
-
-           if (tbmres->ntuples >= 0)
-               node->stats.exact_pages++;
-           else
-               node->stats.lossy_pages++;
-
-           if (!valid_block)
+           if (!table_scan_bitmap_next_block(scan, tbmres,
+                                             &node->stats.lossy_pages,
+                                             &node->stats.exact_pages))
            {
                /* AM doesn't think this block is valid, skip */
                continue;
index da661289c1fd47f842c14595f11361104536d0ee..be09d180d45b98f6b888fb174c33bd66227f6e96 100644 (file)
@@ -796,6 +796,10 @@ typedef struct TableAmRoutine
     * on the page have to be returned, otherwise the tuples at offsets in
     * `tbmres->offsets` need to be returned.
     *
+    * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
+    * incremented by the table AM to indicate whether or not the block's
+    * representation in the bitmap is lossy.
+    *
     * XXX: Currently this may only be implemented if the AM uses md.c as its
     * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
     * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -811,7 +815,9 @@ typedef struct TableAmRoutine
     * scan_bitmap_next_tuple need to exist, or neither.
     */
    bool        (*scan_bitmap_next_block) (TableScanDesc scan,
-                                          struct TBMIterateResult *tbmres);
+                                          struct TBMIterateResult *tbmres,
+                                          uint64 *lossy_pages,
+                                          uint64 *exact_pages);
 
    /*
     * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1954,12 +1960,18 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
  * the page, true otherwise.
  *
+ * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
+ * incremented by the table AM to indicate whether or not the block's
+ * representation in the bitmap is lossy.
+ *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-                            struct TBMIterateResult *tbmres)
+                            struct TBMIterateResult *tbmres,
+                            uint64 *lossy_pages,
+                            uint64 *exact_pages)
 {
    /*
     * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1970,7 +1982,9 @@ table_scan_bitmap_next_block(TableScanDesc scan,
        elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
    return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-                                                          tbmres);
+                                                          tbmres,
+                                                          lossy_pages,
+                                                          exact_pages);
 }
 
 /*