1515#include <sys/stat.h>
1616#include <unistd.h>
1717
18+ #include "access/heapam.h"
1819#include "access/relation.h"
1920#include "fmgr.h"
2021#include "miscadmin.h"
@@ -38,6 +39,7 @@ typedef enum
3839 PREWARM_PREFETCH ,
3940 PREWARM_READ ,
4041 PREWARM_BUFFER ,
42+ PREWARM_TUPLE ,
4143} PrewarmType ;
4244
4345static PGIOAlignedBlock blockbuffer ;
@@ -90,6 +92,8 @@ pg_prewarm(PG_FUNCTION_ARGS)
9092 ptype = PREWARM_READ ;
9193 else if (strcmp (ttype , "buffer" ) == 0 )
9294 ptype = PREWARM_BUFFER ;
95+ else if (strcmp (ttype , "tuple" ) == 0 )
96+ ptype = PREWARM_TUPLE ;
9397 else
9498 {
9599 ereport (ERROR ,
@@ -231,6 +235,32 @@ pg_prewarm(PG_FUNCTION_ARGS)
231235 }
232236 Assert (read_stream_next_buffer (stream , NULL ) == InvalidBuffer );
233237 read_stream_end (stream );
238+ } else if (ptype == PREWARM_TUPLE )
239+ {
240+ if (get_relkind_objtype (rel -> rd_rel -> relkind ) == OBJECT_TABLE && forkNumber == MAIN_FORKNUM )
241+ {
242+ uint32 scan_flags = SO_TYPE_SEQSCAN | SO_TEMP_SNAPSHOT ;
243+ HeapTuple tuple ;
244+ Snapshot snapshot ;
245+ TableScanDesc scan ;
246+
247+ elog (LOG , "pg_prewarm: SeqScan relation \"%s\" starting %ld for %ld blocks" , RelationGetRelationName (rel ), first_block , last_block - first_block + 1 );
248+ // Use heap scan to set hint bits on every tuple. SO_ALLOW_PAGEMODE is intentionally NOT SET.
249+ // Otherwise, when a page is all visible, tuple hint bits won't be set.
250+ snapshot = RegisterSnapshot (GetTransactionSnapshot ());
251+ scan = heap_beginscan (rel , snapshot , 0 , NULL , NULL , scan_flags );
252+ heap_setscanlimits (scan , first_block , last_block - first_block + 1 );
253+ while ((tuple = heap_getnext (scan , ForwardScanDirection )) != NULL )
254+ {
255+ CHECK_FOR_INTERRUPTS ();
256+ }
257+ heap_endscan (scan );
258+ } else
259+ {
260+ ereport (INFO ,
261+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
262+ errmsg ("tuple prewarm is only supported for heap relations on main fork" )));
263+ }
234264 }
235265
236266 /* Close relation, release lock. */
0 commit comments