diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 8837f83..c87fd47 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -162,6 +162,14 @@ static const struct
 #define ConditionalLockTupleTuplock(rel, tup, mode) \
 	ConditionalLockTuple((rel), (tup), tupleLockExtraInfo[mode].hwlock)
 
+#ifdef USE_PREFETCH
+typedef struct
+{
+	int		next_item;
+	BlockNumber		cur_hblkno;
+} PrefetchState;
+#endif
+
 /*
  * This table maps tuple lock strength values for each particular
  * MultiXactStatus value.
@@ -6990,6 +6998,45 @@ HeapTupleHeaderAdvanceLatestRemovedXid(HeapTupleHeader tuple,
 	/* *latestRemovedXid may still be invalid at end */
 }
 
+#ifdef USE_PREFETCH
+/*
+ * prefetch_buffer
+ *
+ * Pre-fetch 'prefetch_count' numnber of buffers.
+ * Continues to scan the tids array from the last position that was scanned
+ * for previous pre-fetching.
+ */
+static void
+prefetch_buffer(Relation rel, PrefetchState *prefetch_state,
+				ItemPointerData *tids, int nitems, int prefetch_count)
+{
+	int		count = 0;
+	BlockNumber		hblkno = prefetch_state->cur_hblkno;
+	int		i;
+
+	for (i = prefetch_state->next_item; i < nitems && count < prefetch_count; i++)
+	{
+		ItemPointer htid = &tids[i];
+
+		if (hblkno == InvalidBlockNumber ||
+			ItemPointerGetBlockNumber(htid) != hblkno)
+		{
+			hblkno = ItemPointerGetBlockNumber(htid);
+
+			count++;
+			PrefetchBuffer(rel, MAIN_FORKNUM, hblkno);
+		}
+	}
+
+	/*
+	 * Keep track of the item pointer array position, so that next time we can
+	 * continue from this position.
+	 */
+	prefetch_state->next_item = i;
+	prefetch_state->cur_hblkno = hblkno;
+}
+#endif
+
 /*
  * Get the latestRemovedXid from the heap pages pointed at by the index
  * tuples being deleted.
@@ -7011,6 +7058,7 @@ heap_compute_xid_horizon_for_tuples(Relation rel,
 	BlockNumber hblkno;
 	Buffer		buf = InvalidBuffer;
 	Page		hpage;
+	PrefetchState prefetch_state;
 
 	/*
 	 * Sort to avoid repeated lookups for the same page, and to make it more
@@ -7023,19 +7071,10 @@ heap_compute_xid_horizon_for_tuples(Relation rel,
 
 	/* prefetch all pages */
 #ifdef USE_PREFETCH
-	hblkno = InvalidBlockNumber;
-	for (int i = 0; i < nitems; i++)
-	{
-		ItemPointer htid = &tids[i];
-
-		if (hblkno == InvalidBlockNumber ||
-			ItemPointerGetBlockNumber(htid) != hblkno)
-		{
-			hblkno = ItemPointerGetBlockNumber(htid);
-
-			PrefetchBuffer(rel, MAIN_FORKNUM, hblkno);
-		}
-	}
+	prefetch_state.next_item = 0;
+	prefetch_state.cur_hblkno = InvalidBlockNumber;
+	prefetch_buffer(rel, &prefetch_state, tids, nitems,
+					5 /* prefetch distance ; TODO: use effective_io_concurrency */);
 #endif
 
 	/* Iterate over all tids, and check their horizon */
@@ -7063,6 +7102,13 @@ heap_compute_xid_horizon_for_tuples(Relation rel,
 			hblkno = ItemPointerGetBlockNumber(htid);
 
 			buf = ReadBuffer(rel, hblkno);
+
+			/*
+			 * Need to maintain the prefetch distance, so prefetch a page each
+			 * time we read a new page.
+			 */
+			prefetch_buffer(rel, &prefetch_state, tids, nitems, 1);
+
 			hpage = BufferGetPage(buf);
 
 			LockBuffer(buf, BUFFER_LOCK_SHARE);
