heapam: Only set tuple's block once per page in pagemode
authorHeikki Linnakangas <[email protected]>
Tue, 1 Apr 2025 10:24:27 +0000 (13:24 +0300)
committerHeikki Linnakangas <[email protected]>
Tue, 1 Apr 2025 10:24:27 +0000 (13:24 +0300)
Due to splitting the block id into two 16 bit integers, BlockIdSet()
is more expensive than one might think.  Doing it once per returned
tuple shows up as a small but reliably reproducible cost.  It's simple
enough to set the block number just once per block in pagemode, so do
so.

Author: Andres Freund <[email protected]>
Discussion: https://www.postgresql.org/message-id/lxzj26ga6ippdeunz6kuncectr5gfuugmm2ry22qu6hcx6oid6@lzx3sjsqhmt6

src/backend/access/heap/heapam.c

index 6e433db039ebb8b323a5cf7c25e67962a6c5f671..cedaa195cb6fa3f3465dc73a53c6321ec07686ea 100644 (file)
@@ -1052,6 +1052,9 @@ heapgettup_pagemode(HeapScanDesc scan,
        linesleft = scan->rs_ntuples;
        lineindex = ScanDirectionIsForward(dir) ? 0 : linesleft - 1;
 
+       /* block is the same for all tuples, set it once outside the loop */
+       ItemPointerSetBlockNumber(&tuple->t_self, scan->rs_cblock);
+
        /* lineindex now references the next or previous visible tid */
 continue_page:
 
@@ -1067,7 +1070,7 @@ continue_page:
 
            tuple->t_data = (HeapTupleHeader) PageGetItem(page, lpp);
            tuple->t_len = ItemIdGetLength(lpp);
-           ItemPointerSet(&(tuple->t_self), scan->rs_cblock, lineoff);
+           ItemPointerSetOffsetNumber(&tuple->t_self, lineoff);
 
            /* skip any tuples that don't match the scan key */
            if (key != NULL &&