On 7/23/25 17:09, Andres Freund wrote:
> Hi,
> 
> On 2025-07-23 14:50:15 +0200, Tomas Vondra wrote:
>> On 7/23/25 02:59, Andres Freund wrote:
>>> Hi,
>>>
>>> On 2025-07-23 02:50:04 +0200, Tomas Vondra wrote:
>>>> But I don't see why would this have any effect on the prefetch distance,
>>>> queue depth etc. Or why decreasing INDEX_SCAN_MAX_BATCHES should improve
>>>> that. I'd have expected exactly the opposite behavior.
>>>>
>>>> Could be bug, of course. But it'd be helpful to see the dataset/query.
>>>
>>> Pgbench scale 500, with the simpler query from my message.
>>>
>>
>> I tried to reproduce this, but I'm not seeing behavior. I'm not sure how
>> you monitor the queue depth (presumably iostat?)
> 
> Yes, iostat, since I was looking at what the "actually required" lookahead
> distance is.
> 
> Do you actually get the query to be entirely CPU bound? What amount of IO
> waiting do you see EXPLAIN (ANALYZE, TIMING OFF) with track_io_timing=on
> report?
> 

No, it definitely needs to wait for I/O (FWIW it's on the xeon, with a
single NVMe SSD).

> Ah - I was using a very high effective_io_concurrency. With a high
> effective_io_concurrency value I see a lot of stalls, even at
> INDEX_SCAN_MAX_BATCHES = 64. And a lower prefetch distance, which seems
> somewhat odd.
> 

I think that's a bug in the explain patch. The counters were updated at
the beginning of _next_buffer(), but that's wrong - a single call to
_next_buffer() can prefetch multiple blocks. This skewed the stats, as
the prefetches are not counted with "distance=0". With higher eic this
happens sooner, so the average distance seemed to decrease.

The attached patch does the updates in _get_block(), which I think is
better. And "stall" now means (distance == 1), which I think detects
requests without prefetching.

I also added a separate "Count" for the actual number of prefetched
blocks, and "Skipped" for duplicate blocks skipped (which the read
stream never even sees, because it's skipped in the callback).

> 
> FWIW, in my tests I was just evicting lineitem from shared buffers, since I
> wanted to test the heap prefetching, without stalls induced by blocking on
> index reads. But what I described happens with either.
> 
> ;SET effective_io_concurrency = 256;SELECT 
> pg_buffercache_evict_relation('pgbench_accounts'); explain (analyze, costs 
> off, timing off) SELECT max(abalance) FROM (SELECT * FROM pgbench_accounts 
> ORDER BY aid LIMIT 10000000);
> ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────┐
> │                                                QUERY PLAN                   
>                              │
> ├──────────────────────────────────────────────────────────────────────────────────────────────────────────┤
> │ Aggregate (actual rows=1.00 loops=1)                                        
>                              │
> │   Buffers: shared hit=27369 read=164191                                     
>                              │
> │   I/O Timings: shared read=358.795                                          
>                              │
> │   ->  Limit (actual rows=10000000.00 loops=1)                               
>                              │
> │         Buffers: shared hit=27369 read=164191                               
>                              │
> │         I/O Timings: shared read=358.795                                    
>                              │
> │         ->  Index Scan using pgbench_accounts_pkey on pgbench_accounts 
> (actual rows=10000000.00 loops=1) │
> │               Index Searches: 1                                             
>                              │
> │               Prefetch Distance: 256.989                                    
>                              │
> │               Prefetch Stalls: 3                                            
>                              │
> │               Prefetch Resets: 3                                            
>                              │
> │               Buffers: shared hit=27369 read=164191                         
>                              │
> │               I/O Timings: shared read=358.795                              
>                              │
> │ Planning Time: 0.086 ms                                                     
>                              │
> │ Execution Time: 4194.845 ms                                                 
>                              │
> └──────────────────────────────────────────────────────────────────────────────────────────────────────────┘
> 
> ;SET effective_io_concurrency = 512;SELECT 
> pg_buffercache_evict_relation('pgbench_accounts'); explain (analyze, costs 
> off, timing off) SELECT max(abalance) FROM (SELECT * FROM pgbench_accounts 
> ORDER BY aid LIMIT 10000000);
> ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────┐
> │                                                QUERY PLAN                   
>                              │
> ├──────────────────────────────────────────────────────────────────────────────────────────────────────────┤
> │ Aggregate (actual rows=1.00 loops=1)                                        
>                              │
> │   Buffers: shared hit=27368 read=164190                                     
>                              │
> │   I/O Timings: shared read=832.515                                          
>                              │
> │   ->  Limit (actual rows=10000000.00 loops=1)                               
>                              │
> │         Buffers: shared hit=27368 read=164190                               
>                              │
> │         I/O Timings: shared read=832.515                                    
>                              │
> │         ->  Index Scan using pgbench_accounts_pkey on pgbench_accounts 
> (actual rows=10000000.00 loops=1) │
> │               Index Searches: 1                                             
>                              │
> │               Prefetch Distance: 56.778                                     
>                              │
> │               Prefetch Stalls: 160569                                       
>                              │
> │               Prefetch Resets: 423                                          
>                              │
> │               Buffers: shared hit=27368 read=164190                         
>                              │
> │               I/O Timings: shared read=832.515                              
>                              │
> │ Planning Time: 0.084 ms                                                     
>                              │
> │ Execution Time: 4413.058 ms                                                 
>                              │
> └──────────────────────────────────────────────────────────────────────────────────────────────────────────┘
> 
> Greetings,
> 

The attached v2 explain patch should fix that. I'm also attaching logs
from my explain, for 64 and 16 batches. I think the output makes much
more sense now.


cheers

-- 
Tomas Vondra
====================== eic 1 ========================
SET
                                                QUERY PLAN                                                
----------------------------------------------------------------------------------------------------------
 Aggregate (actual rows=1.00 loops=1)
   Buffers: shared read=191281
   I/O Timings: shared read=3341.988
   ->  Limit (actual rows=10000000.00 loops=1)
         Buffers: shared read=191281
         I/O Timings: shared read=3341.988
         ->  Index Scan using pgbench_accounts_pkey on pgbench_accounts (actual rows=10000000.00 loops=1)
               Index Searches: 1
               Prefetch Distance: 31.996
               Prefetch Count: 163951
               Prefetch Stalls: 1
               Prefetch Skips: 9837060
               Prefetch Resets: 3
               Buffers: shared read=191281
               I/O Timings: shared read=3341.988
 Planning:
   Buffers: shared hit=46 read=22
   I/O Timings: shared read=2.595
 Planning Time: 4.711 ms
 Execution Time: 5948.513 ms
(20 rows)

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
nvme0n1p1     6046.00 241029.00     0.00   0.00    0.09    39.87    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.57  59.20
nvme0n1p1     6368.00 258944.00     0.00   0.00    0.09    40.66    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.56  60.00
nvme0n1p1     6323.00 257136.00     0.00   0.00    0.09    40.67    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.57  58.40
nvme0n1p1     6258.00 254328.00     0.00   0.00    0.09    40.64    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.57  54.80
nvme0n1p1     6414.00 260896.00     0.00   0.00    0.09    40.68    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.56  63.60
====================== eic 8 ========================
SET
                                                QUERY PLAN                                                
----------------------------------------------------------------------------------------------------------
 Aggregate (actual rows=1.00 loops=1)
   Buffers: shared read=191411
   I/O Timings: shared read=763.833
   ->  Limit (actual rows=10000000.00 loops=1)
         Buffers: shared read=191411
         I/O Timings: shared read=763.833
         ->  Index Scan using pgbench_accounts_pkey on pgbench_accounts (actual rows=10000000.00 loops=1)
               Index Searches: 1
               Prefetch Distance: 143.923
               Prefetch Count: 164063
               Prefetch Stalls: 1
               Prefetch Skips: 9843780
               Prefetch Resets: 3
               Buffers: shared read=191411
               I/O Timings: shared read=763.833
 Planning:
   Buffers: shared hit=46 read=22
   I/O Timings: shared read=2.601
 Planning Time: 7.373 ms
 Execution Time: 3045.476 ms
(20 rows)

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
nvme0n1p1     11406.00 458925.00     0.00   0.00    0.09    40.24   14.00     97.50     0.00   0.00    0.07     6.96    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    1.08  86.00
nvme0n1p1     12564.00 510848.00     0.00   0.00    0.09    40.66    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    1.15  90.40
nvme0n1p1     12666.00 515376.00     0.00   0.00    0.09    40.69    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    1.09  90.80
====================== eic 16 ========================
SET
                                                QUERY PLAN                                                
----------------------------------------------------------------------------------------------------------
 Aggregate (actual rows=1.00 loops=1)
   Buffers: shared read=191561
   I/O Timings: shared read=780.076
   ->  Limit (actual rows=10000000.00 loops=1)
         Buffers: shared read=191561
         I/O Timings: shared read=780.076
         ->  Index Scan using pgbench_accounts_pkey on pgbench_accounts (actual rows=10000000.00 loops=1)
               Index Searches: 1
               Prefetch Distance: 271.761
               Prefetch Count: 164191
               Prefetch Stalls: 1
               Prefetch Skips: 9851460
               Prefetch Resets: 3
               Buffers: shared read=191561
               I/O Timings: shared read=780.076
 Planning:
   Buffers: shared hit=46 read=22
   I/O Timings: shared read=2.581
 Planning Time: 7.476 ms
 Execution Time: 3025.995 ms
(20 rows)

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
nvme0n1p1     11731.00 472197.00     0.00   0.00    0.09    40.25    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    1.09  90.40
nvme0n1p1     12446.00 505944.00     0.00   0.00    0.09    40.65    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    1.14  90.40
nvme0n1p1     12751.00 518936.00     0.00   0.00    0.09    40.70    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    1.10  95.60
====================== eic 32 ========================
SET
                                                QUERY PLAN                                                
----------------------------------------------------------------------------------------------------------
 Aggregate (actual rows=1.00 loops=1)
   Buffers: shared read=191348
   I/O Timings: shared read=1283.840
   ->  Limit (actual rows=10000000.00 loops=1)
         Buffers: shared read=191348
         I/O Timings: shared read=1283.840
         ->  Index Scan using pgbench_accounts_pkey on pgbench_accounts (actual rows=10000000.00 loops=1)
               Index Searches: 1
               Prefetch Distance: 253.411
               Prefetch Count: 164010
               Prefetch Stalls: 355
               Prefetch Skips: 9840600
               Prefetch Resets: 357
               Buffers: shared read=191348
               I/O Timings: shared read=1283.840
 Planning:
   Buffers: shared hit=46 read=22
   I/O Timings: shared read=2.693
 Planning Time: 7.426 ms
 Execution Time: 3618.736 ms
(20 rows)

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
nvme0n1p1     10195.00 398333.00     0.00   0.00    0.11    39.07    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    1.12  52.40
nvme0n1p1     10506.00 414456.00     0.00   0.00    0.11    39.45    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    1.16  54.80
nvme0n1p1     10899.00 430776.00     0.00   0.00    0.11    39.52    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    1.17  55.20
====================== eic 64 ========================
SET
                                                QUERY PLAN                                                
----------------------------------------------------------------------------------------------------------
 Aggregate (actual rows=1.00 loops=1)
   Buffers: shared read=191348
   I/O Timings: shared read=1427.778
   ->  Limit (actual rows=10000000.00 loops=1)
         Buffers: shared read=191348
         I/O Timings: shared read=1427.778
         ->  Index Scan using pgbench_accounts_pkey on pgbench_accounts (actual rows=10000000.00 loops=1)
               Index Searches: 1
               Prefetch Distance: 253.411
               Prefetch Count: 164010
               Prefetch Stalls: 355
               Prefetch Skips: 9840600
               Prefetch Resets: 357
               Buffers: shared read=191348
               I/O Timings: shared read=1427.778
 Planning:
   Buffers: shared hit=46 read=22
   I/O Timings: shared read=3.138
 Planning Time: 7.869 ms
 Execution Time: 3829.833 ms
(20 rows)

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
nvme0n1p1     9217.00 359565.00     0.00   0.00    0.11    39.01    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    1.01  48.00
nvme0n1p1     10042.00 396664.00     0.00   0.00    0.11    39.50    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    1.07  50.40
nvme0n1p1     10162.00 401184.00     0.00   0.00    0.11    39.48    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    1.11  53.60
====================== eic 128 ========================
SET
                                                QUERY PLAN                                                
----------------------------------------------------------------------------------------------------------
 Aggregate (actual rows=1.00 loops=1)
   Buffers: shared read=191348
   I/O Timings: shared read=1374.205
   ->  Limit (actual rows=10000000.00 loops=1)
         Buffers: shared read=191348
         I/O Timings: shared read=1374.205
         ->  Index Scan using pgbench_accounts_pkey on pgbench_accounts (actual rows=10000000.00 loops=1)
               Index Searches: 1
               Prefetch Distance: 253.411
               Prefetch Count: 164010
               Prefetch Stalls: 355
               Prefetch Skips: 9840600
               Prefetch Resets: 357
               Buffers: shared read=191348
               I/O Timings: shared read=1374.205
 Planning:
   Buffers: shared hit=46 read=22
   I/O Timings: shared read=2.979
 Planning Time: 7.543 ms
 Execution Time: 3808.224 ms
(20 rows)

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
nvme0n1p1     9641.00 376724.00     0.00   0.00    0.11    39.08    1.00      9.50     0.00   0.00    0.00     9.50    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    1.06  51.20
nvme0n1p1     10193.00 401992.00     0.00   0.00    0.11    39.44    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    1.10  50.80
nvme0n1p1     10332.00 408664.00     0.00   0.00    0.11    39.55    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    1.10  51.20
====================== eic 256 ========================
SET
                                                QUERY PLAN                                                
----------------------------------------------------------------------------------------------------------
 Aggregate (actual rows=1.00 loops=1)
   Buffers: shared read=191348
   I/O Timings: shared read=1330.131
   ->  Limit (actual rows=10000000.00 loops=1)
         Buffers: shared read=191348
         I/O Timings: shared read=1330.131
         ->  Index Scan using pgbench_accounts_pkey on pgbench_accounts (actual rows=10000000.00 loops=1)
               Index Searches: 1
               Prefetch Distance: 253.411
               Prefetch Count: 164010
               Prefetch Stalls: 355
               Prefetch Skips: 9840600
               Prefetch Resets: 357
               Buffers: shared read=191348
               I/O Timings: shared read=1330.131
 Planning:
   Buffers: shared hit=46 read=22
   I/O Timings: shared read=2.566
 Planning Time: 6.547 ms
 Execution Time: 3674.986 ms
(20 rows)

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
nvme0n1p1     10039.00 391733.00     0.00   0.00    0.11    39.02    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    1.10  51.60
nvme0n1p1     10422.00 411928.00     0.00   0.00    0.11    39.52    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    1.15  53.60
nvme0n1p1     10843.00 427872.00     0.00   0.00    0.11    39.46    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    1.16  51.20
====================== eic 512 ========================
SET
                                                QUERY PLAN                                                
----------------------------------------------------------------------------------------------------------
 Aggregate (actual rows=1.00 loops=1)
   Buffers: shared read=191348
   I/O Timings: shared read=1367.977
   ->  Limit (actual rows=10000000.00 loops=1)
         Buffers: shared read=191348
         I/O Timings: shared read=1367.977
         ->  Index Scan using pgbench_accounts_pkey on pgbench_accounts (actual rows=10000000.00 loops=1)
               Index Searches: 1
               Prefetch Distance: 253.411
               Prefetch Count: 164010
               Prefetch Stalls: 355
               Prefetch Skips: 9840600
               Prefetch Resets: 357
               Buffers: shared read=191348
               I/O Timings: shared read=1367.977
 Planning:
   Buffers: shared hit=46 read=22
   I/O Timings: shared read=3.124
 Planning Time: 8.065 ms
 Execution Time: 3828.742 ms
(20 rows)

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
nvme0n1p1     9439.00 368301.00     0.00   0.00    0.11    39.02    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    1.04  51.20
nvme0n1p1     10048.00 396720.00     0.00   0.00    0.11    39.48    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    1.09  51.60
nvme0n1p1     10251.00 405160.00     0.00   0.00    0.11    39.52    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    1.09  51.20
====================== eic 1 ========================
SET
                                                QUERY PLAN                                                
----------------------------------------------------------------------------------------------------------
 Aggregate (actual rows=1.00 loops=1)
   Buffers: shared read=191281
   I/O Timings: shared read=3013.116
   ->  Limit (actual rows=10000000.00 loops=1)
         Buffers: shared read=191281
         I/O Timings: shared read=3013.116
         ->  Index Scan using pgbench_accounts_pkey on pgbench_accounts (actual rows=10000000.00 loops=1)
               Index Searches: 1
               Prefetch Distance: 31.996
               Prefetch Count: 163951
               Prefetch Stalls: 1
               Prefetch Skips: 9837060
               Prefetch Resets: 3
               Buffers: shared read=191281
               I/O Timings: shared read=3013.116
 Planning:
   Buffers: shared hit=46 read=22
   I/O Timings: shared read=2.550
 Planning Time: 6.822 ms
 Execution Time: 5279.929 ms
(20 rows)

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
nvme0n1p1     6710.00 268196.50     0.00   0.00    0.10    39.97    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.64  60.00
nvme0n1p1     7122.00 289432.00     0.00   0.00    0.09    40.64    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.63  62.00
nvme0n1p1     6811.00 276864.00     0.00   0.00    0.10    40.65    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.66  63.60
nvme0n1p1     7209.00 293144.00     0.00   0.00    0.09    40.66    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.65  72.80
nvme0n1p1     7519.00 306128.00     0.00   0.00    0.08    40.71    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.64  65.60
====================== eic 8 ========================
SET
                                                QUERY PLAN                                                
----------------------------------------------------------------------------------------------------------
 Aggregate (actual rows=1.00 loops=1)
   Buffers: shared read=191271
   I/O Timings: shared read=2625.972
   ->  Limit (actual rows=10000000.00 loops=1)
         Buffers: shared read=191271
         I/O Timings: shared read=2625.972
         ->  Index Scan using pgbench_accounts_pkey on pgbench_accounts (actual rows=10000000.00 loops=1)
               Index Searches: 1
               Prefetch Distance: 58.116
               Prefetch Count: 163944
               Prefetch Stalls: 1188
               Prefetch Skips: 9836640
               Prefetch Resets: 1190
               Buffers: shared read=191271
               I/O Timings: shared read=2625.972
 Planning:
   Buffers: shared hit=46 read=22
   I/O Timings: shared read=2.656
 Planning Time: 6.605 ms
 Execution Time: 5102.460 ms
(20 rows)

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
nvme0n1p1     7681.00 278516.00     0.00   0.00    0.11    36.26   19.00    143.00     0.00   0.00    0.11     7.53    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.86  52.40
nvme0n1p1     8316.00 305400.00     0.00   0.00    0.11    36.72    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.89  62.00
nvme0n1p1     7695.00 282568.00     0.00   0.00    0.12    36.72    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.90  64.80
nvme0n1p1     8350.00 307192.00     0.00   0.00    0.11    36.79    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.89  55.60
nvme0n1p1     8399.00 308768.00     0.00   0.00    0.11    36.76    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.88  60.80
====================== eic 16 ========================
SET
                                                QUERY PLAN                                                
----------------------------------------------------------------------------------------------------------
 Aggregate (actual rows=1.00 loops=1)
   Buffers: shared read=191271
   I/O Timings: shared read=2705.352
   ->  Limit (actual rows=10000000.00 loops=1)
         Buffers: shared read=191271
         I/O Timings: shared read=2705.352
         ->  Index Scan using pgbench_accounts_pkey on pgbench_accounts (actual rows=10000000.00 loops=1)
               Index Searches: 1
               Prefetch Distance: 58.116
               Prefetch Count: 163944
               Prefetch Stalls: 1188
               Prefetch Skips: 9836640
               Prefetch Resets: 1190
               Buffers: shared read=191271
               I/O Timings: shared read=2705.352
 Planning:
   Buffers: shared hit=46 read=22
   I/O Timings: shared read=3.004
 Planning Time: 7.725 ms
 Execution Time: 5308.190 ms
(20 rows)

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
nvme0n1p1     7107.00 256981.00     0.00   0.00    0.11    36.16    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.78  51.60
nvme0n1p1     7879.00 289552.00     0.00   0.00    0.10    36.75    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.81  49.20
nvme0n1p1     7671.00 281904.00     0.00   0.00    0.11    36.75    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.82  55.20
nvme0n1p1     8136.00 298944.00     0.00   0.00    0.10    36.74    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.84  59.20
nvme0n1p1     7933.00 291688.00     0.00   0.00    0.11    36.77    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.85  56.80
====================== eic 32 ========================
SET
                                                QUERY PLAN                                                
----------------------------------------------------------------------------------------------------------
 Aggregate (actual rows=1.00 loops=1)
   Buffers: shared read=191271
   I/O Timings: shared read=2931.130
   ->  Limit (actual rows=10000000.00 loops=1)
         Buffers: shared read=191271
         I/O Timings: shared read=2931.130
         ->  Index Scan using pgbench_accounts_pkey on pgbench_accounts (actual rows=10000000.00 loops=1)
               Index Searches: 1
               Prefetch Distance: 58.116
               Prefetch Count: 163944
               Prefetch Stalls: 1188
               Prefetch Skips: 9836640
               Prefetch Resets: 1190
               Buffers: shared read=191271
               I/O Timings: shared read=2931.130
 Planning:
   Buffers: shared hit=46 read=22
   I/O Timings: shared read=2.921
 Planning Time: 6.654 ms
 Execution Time: 5572.837 ms
(20 rows)

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
nvme0n1p1     6674.00 241316.00     0.00   0.00    0.12    36.16    1.00      9.50     0.00   0.00    0.00     9.50    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.79  61.20
nvme0n1p1     7342.00 269680.00     0.00   0.00    0.11    36.73    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.84  57.60
nvme0n1p1     7713.86 283516.83     0.00   0.00    0.11    36.75    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.85  59.41
nvme0n1p1     6987.00 256696.00     0.00   0.00    0.11    36.74    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.80  58.40
nvme0n1p1     7835.00 288344.00     0.00   0.00    0.10    36.80    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.80  54.00
====================== eic 64 ========================
SET
                                                QUERY PLAN                                                
----------------------------------------------------------------------------------------------------------
 Aggregate (actual rows=1.00 loops=1)
   Buffers: shared read=191271
   I/O Timings: shared read=2661.311
   ->  Limit (actual rows=10000000.00 loops=1)
         Buffers: shared read=191271
         I/O Timings: shared read=2661.311
         ->  Index Scan using pgbench_accounts_pkey on pgbench_accounts (actual rows=10000000.00 loops=1)
               Index Searches: 1
               Prefetch Distance: 58.116
               Prefetch Count: 163944
               Prefetch Stalls: 1188
               Prefetch Skips: 9836640
               Prefetch Resets: 1190
               Buffers: shared read=191271
               I/O Timings: shared read=2661.311
 Planning:
   Buffers: shared hit=46 read=22
   I/O Timings: shared read=2.675
 Planning Time: 6.858 ms
 Execution Time: 5239.994 ms
(20 rows)

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
nvme0n1p1     6942.00 251236.00     0.00   0.00    0.12    36.19    1.00      9.50     0.00   0.00    0.00     9.50    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.85  62.00
nvme0n1p1     8176.00 300400.00     0.00   0.00    0.11    36.74    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.87  73.60
nvme0n1p1     7938.00 291496.00     0.00   0.00    0.11    36.72    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.88  72.80
nvme0n1p1     8235.00 302680.00     0.00   0.00    0.10    36.76    1.00      8.00     0.00   0.00    0.00     8.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.86  60.80
nvme0n1p1     8155.00 300080.00     0.00   0.00    0.10    36.80    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.85  59.60
====================== eic 128 ========================
SET
                                                QUERY PLAN                                                
----------------------------------------------------------------------------------------------------------
 Aggregate (actual rows=1.00 loops=1)
   Buffers: shared read=191271
   I/O Timings: shared read=2607.508
   ->  Limit (actual rows=10000000.00 loops=1)
         Buffers: shared read=191271
         I/O Timings: shared read=2607.508
         ->  Index Scan using pgbench_accounts_pkey on pgbench_accounts (actual rows=10000000.00 loops=1)
               Index Searches: 1
               Prefetch Distance: 58.116
               Prefetch Count: 163944
               Prefetch Stalls: 1188
               Prefetch Skips: 9836640
               Prefetch Resets: 1190
               Buffers: shared read=191271
               I/O Timings: shared read=2607.508
 Planning:
   Buffers: shared hit=46 read=22
   I/O Timings: shared read=2.742
 Planning Time: 7.629 ms
 Execution Time: 5110.434 ms
(20 rows)

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
nvme0n1p1     7380.00 267116.50     0.00   0.00    0.12    36.19    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.86  70.40
nvme0n1p1     8236.00 302600.00     0.00   0.00    0.10    36.74    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.86  66.00
nvme0n1p1     7988.12 293394.06     0.00   0.00    0.11    36.73    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.87  61.78
nvme0n1p1     8310.00 305424.00     0.00   0.00    0.10    36.75    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.87  65.60
nvme0n1p1     8542.00 314264.00     0.00   0.00    0.10    36.79    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.87  60.00
====================== eic 256 ========================
SET
                                                QUERY PLAN                                                
----------------------------------------------------------------------------------------------------------
 Aggregate (actual rows=1.00 loops=1)
   Buffers: shared read=191271
   I/O Timings: shared read=2540.047
   ->  Limit (actual rows=10000000.00 loops=1)
         Buffers: shared read=191271
         I/O Timings: shared read=2540.047
         ->  Index Scan using pgbench_accounts_pkey on pgbench_accounts (actual rows=10000000.00 loops=1)
               Index Searches: 1
               Prefetch Distance: 58.116
               Prefetch Count: 163944
               Prefetch Stalls: 1188
               Prefetch Skips: 9836640
               Prefetch Resets: 1190
               Buffers: shared read=191271
               I/O Timings: shared read=2540.047
 Planning:
   Buffers: shared hit=46 read=22
   I/O Timings: shared read=2.644
 Planning Time: 6.982 ms
 Execution Time: 5036.594 ms
(20 rows)

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
nvme0n1p1     7847.00 284436.00     0.00   0.00    0.11    36.25    1.00      9.50     0.00   0.00    0.00     9.50    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.86  56.80
nvme0n1p1     7730.00 284024.00     0.00   0.00    0.11    36.74    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.88  62.40
nvme0n1p1     8462.00 310752.00     0.00   0.00    0.10    36.72    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.88  62.80
nvme0n1p1     8352.00 307328.00     0.00   0.00    0.10    36.80    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.88  74.40
nvme0n1p1     8719.00 320712.00     0.00   0.00    0.10    36.78    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.88  55.60
====================== eic 512 ========================
SET
                                                QUERY PLAN                                                
----------------------------------------------------------------------------------------------------------
 Aggregate (actual rows=1.00 loops=1)
   Buffers: shared read=191271
   I/O Timings: shared read=2510.486
   ->  Limit (actual rows=10000000.00 loops=1)
         Buffers: shared read=191271
         I/O Timings: shared read=2510.486
         ->  Index Scan using pgbench_accounts_pkey on pgbench_accounts (actual rows=10000000.00 loops=1)
               Index Searches: 1
               Prefetch Distance: 58.116
               Prefetch Count: 163944
               Prefetch Stalls: 1188
               Prefetch Skips: 9836640
               Prefetch Resets: 1190
               Buffers: shared read=191271
               I/O Timings: shared read=2510.486
 Planning:
   Buffers: shared hit=46 read=22
   I/O Timings: shared read=2.700
 Planning Time: 7.197 ms
 Execution Time: 5037.071 ms
(20 rows)

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
nvme0n1p1     7379.00 267108.50     0.00   0.00    0.12    36.20    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.86  60.80
nvme0n1p1     8128.00 298680.00     0.00   0.00    0.11    36.75    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.87  62.00
nvme0n1p1     8437.00 309752.00     0.00   0.00    0.11    36.71    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.89  53.60
nvme0n1p1     8609.00 316528.00     0.00   0.00    0.10    36.77    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.88  60.00
nvme0n1p1     8534.00 314016.00     0.00   0.00    0.10    36.80    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.87  68.80
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 4835c48b448..b0e50307a0e 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -407,12 +407,6 @@ index_beginscan_internal(Relation indexRelation,
 	scan->parallel_scan = pscan;
 	scan->xs_temp_snap = temp_snap;
 
-	/*
-	 * No batching by default, so set it to NULL. Will be initialized later if
-	 * batching is requested and AM supports it.
-	 */
-	scan->xs_batches = NULL;
-
 	return scan;
 }
 
@@ -463,6 +457,17 @@ index_rescan(IndexScanDesc scan,
 											orderbys, norderbys);
 }
 
+void
+index_get_prefetch_stats(IndexScanDesc scan, int *accum, int *count, int *stalls, int *resets, int *skips)
+{
+	/* ugly */
+	if (scan->xs_heapfetch->rs != NULL)
+	{
+		read_stream_prefetch_stats(scan->xs_heapfetch->rs,
+					   accum, count, stalls, resets, skips);
+	}
+}
+
 /* ----------------
  *		index_endscan - end a scan
  * ----------------
@@ -1883,6 +1888,7 @@ index_scan_stream_read_next(ReadStream *stream,
 			/* same block as before, don't need to read it */
 			if (scan->xs_batches->lastBlock == ItemPointerGetBlockNumber(tid))
 			{
+				read_stream_skip_block(stream);
 				DEBUG_LOG("index_scan_stream_read_next: skip block (lastBlock)");
 				continue;
 			}
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 7e2792ead71..9c95b4e2878 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -136,6 +136,7 @@ static void show_memoize_info(MemoizeState *mstate, List *ancestors,
 							  ExplainState *es);
 static void show_hashagg_info(AggState *aggstate, ExplainState *es);
 static void show_indexsearches_info(PlanState *planstate, ExplainState *es);
+static void show_indexprefetch_info(PlanState *planstate, ExplainState *es);
 static void show_tidbitmap_info(BitmapHeapScanState *planstate,
 								ExplainState *es);
 static void show_instrumentation_count(const char *qlabel, int which,
@@ -1966,6 +1967,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
 				show_instrumentation_count("Rows Removed by Filter", 1,
 										   planstate, es);
 			show_indexsearches_info(planstate, es);
+			show_indexprefetch_info(planstate, es);
 			break;
 		case T_IndexOnlyScan:
 			show_scan_qual(((IndexOnlyScan *) plan)->indexqual,
@@ -1983,6 +1985,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
 				ExplainPropertyFloat("Heap Fetches", NULL,
 									 planstate->instrument->ntuples2, 0, es);
 			show_indexsearches_info(planstate, es);
+			show_indexprefetch_info(planstate, es);
 			break;
 		case T_BitmapIndexScan:
 			show_scan_qual(((BitmapIndexScan *) plan)->indexqualorig,
@@ -3889,6 +3892,50 @@ show_indexsearches_info(PlanState *planstate, ExplainState *es)
 	ExplainPropertyUInteger("Index Searches", NULL, nsearches, es);
 }
 
+static void
+show_indexprefetch_info(PlanState *planstate, ExplainState *es)
+{
+	Plan       *plan = planstate->plan;
+
+	int	count = 0,
+		accum = 0,
+		stalls = 0,
+		resets = 0,
+		skips = 0;
+
+	if (!es->analyze)
+		return;
+
+	/* Initialize counters with stats from the local process first */
+	switch (nodeTag(plan))
+	{
+		case T_IndexScan:
+			{
+				IndexScanState *indexstate = ((IndexScanState *) planstate);
+
+				count = indexstate->iss_PrefetchCount;
+				accum = indexstate->iss_PrefetchAccum;
+				stalls = indexstate->iss_PrefetchStalls;
+				resets = indexstate->iss_ResetCount;
+				skips = indexstate->iss_SkipCount;
+
+				break;
+			}
+		default:
+			break;
+	}
+
+	if (count > 0)
+	{
+		ExplainPropertyFloat("Prefetch Distance", NULL, (accum * 1.0 / count), 3, es);
+		ExplainPropertyUInteger("Prefetch Count", NULL, count, es);
+		ExplainPropertyUInteger("Prefetch Stalls", NULL, stalls, es);
+		ExplainPropertyUInteger("Prefetch Skips", NULL, skips, es);
+		ExplainPropertyUInteger("Prefetch Resets", NULL, resets, es);
+	}
+}
+
+
 /*
  * Show exact/lossy pages for a BitmapHeapScan node
  */
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 7fcaa37fe62..707badc4fdc 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -125,6 +125,13 @@ IndexNext(IndexScanState *node)
 						 node->iss_OrderByKeys, node->iss_NumOrderByKeys);
 	}
 
+	index_get_prefetch_stats(scandesc,
+				 &node->iss_PrefetchAccum,
+				 &node->iss_PrefetchCount,
+				 &node->iss_PrefetchStalls,
+				 &node->iss_ResetCount,
+				 &node->iss_SkipCount);
+
 	/*
 	 * ok, now that we have what we need, fetch the next tuple.
 	 */
@@ -1088,6 +1095,12 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
 		indexstate->iss_RuntimeContext = NULL;
 	}
 
+	indexstate->iss_PrefetchAccum = 0;
+	indexstate->iss_PrefetchCount = 0;
+	indexstate->iss_PrefetchStalls = 0;
+	indexstate->iss_ResetCount = 0;
+	indexstate->iss_SkipCount = 0;
+
 	/*
 	 * all done.
 	 */
diff --git a/src/backend/storage/aio/read_stream.c b/src/backend/storage/aio/read_stream.c
index 0e7f5557f5c..e41189f6612 100644
--- a/src/backend/storage/aio/read_stream.c
+++ b/src/backend/storage/aio/read_stream.c
@@ -106,6 +106,12 @@ struct ReadStream
 	bool		advice_enabled;
 	bool		temporary;
 
+	int		distance_accum;
+	int		distance_count;
+	int		distance_stalls;
+	int		reset_count;
+	int		skip_count;
+
 	/*
 	 * One-block buffer to support 'ungetting' a block number, to resolve flow
 	 * control problems when I/Os are split.
@@ -180,6 +186,16 @@ read_stream_get_block(ReadStream *stream, void *per_buffer_data)
 {
 	BlockNumber blocknum;
 
+        if (stream->distance > 1)
+        {
+                stream->distance_accum += stream->distance;
+                stream->distance_count += 1;
+        }
+        else
+        {
+                stream->distance_stalls += 1;
+        }
+
 	blocknum = stream->buffered_blocknum;
 	if (blocknum != InvalidBlockNumber)
 		stream->buffered_blocknum = InvalidBlockNumber;
@@ -681,6 +697,12 @@ read_stream_begin_impl(int flags,
 	stream->seq_until_processed = InvalidBlockNumber;
 	stream->temporary = SmgrIsTemp(smgr);
 
+	stream->distance_accum = 0;
+	stream->distance_count = 0;
+	stream->distance_stalls = 0;
+	stream->reset_count = 0;
+	stream->skip_count = 0;
+
 	/*
 	 * Skip the initial ramp-up phase if the caller says we're going to be
 	 * reading the whole relation.  This way we start out assuming we'll be
@@ -771,6 +793,17 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
 {
 	Buffer		buffer;
 	int16		oldest_buffer_index;
+/*
+	if (stream->distance > 0)
+	{
+		stream->distance_accum += stream->distance;
+		stream->distance_count += 1;
+	}
+	else
+	{
+		stream->distance_stalls += 1;
+	}
+*/
 
 #ifndef READ_STREAM_DISABLE_FAST_PATH
 
@@ -1046,6 +1079,8 @@ read_stream_reset(ReadStream *stream)
 
 	/* Start off assuming data is cached. */
 	stream->distance = 1;
+
+	stream->reset_count += 1;
 }
 
 /*
@@ -1057,3 +1092,19 @@ read_stream_end(ReadStream *stream)
 	read_stream_reset(stream);
 	pfree(stream);
 }
+
+void
+read_stream_prefetch_stats(ReadStream *stream, int *accum, int *count, int *stalls, int *resets, int *skips)
+{
+	*accum = stream->distance_accum;
+	*count = stream->distance_count;
+	*stalls = stream->distance_stalls;
+	*resets = stream->reset_count;
+	*skips = stream->skip_count;
+}
+
+void
+read_stream_skip_block(ReadStream *stream)
+{
+	stream->skip_count++;
+}
diff --git a/src/include/access/genam.h b/src/include/access/genam.h
index 3a3a44be3a5..f1e5fdfd478 100644
--- a/src/include/access/genam.h
+++ b/src/include/access/genam.h
@@ -235,6 +235,7 @@ extern bytea *index_opclass_options(Relation indrel, AttrNumber attnum,
 									Datum attoptions, bool validate);
 extern IndexScanBatch index_batch_alloc(int maxitems, bool want_itup);
 
+extern void index_get_prefetch_stats(IndexScanDesc scan, int *accum, int *count, int *stalls, int *resets, int *skips);
 
 /*
  * index access method support routines (in genam.c)
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index e107d6e5f81..e91bc7ea35f 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1722,6 +1722,12 @@ typedef struct IndexScanState
 	IndexScanInstrumentation iss_Instrument;
 	SharedIndexScanInstrumentation *iss_SharedInfo;
 
+	int		iss_PrefetchAccum;
+	int		iss_PrefetchCount;
+	int		iss_PrefetchStalls;
+	int		iss_ResetCount;
+	int		iss_SkipCount;
+
 	/* These are needed for re-checking ORDER BY expr ordering */
 	pairingheap *iss_ReorderQueue;
 	bool		iss_ReachedEnd;
diff --git a/src/include/storage/read_stream.h b/src/include/storage/read_stream.h
index 9b0d65161d0..34e184a1690 100644
--- a/src/include/storage/read_stream.h
+++ b/src/include/storage/read_stream.h
@@ -102,4 +102,7 @@ extern ReadStream *read_stream_begin_smgr_relation(int flags,
 extern void read_stream_reset(ReadStream *stream);
 extern void read_stream_end(ReadStream *stream);
 
+extern void read_stream_prefetch_stats(ReadStream *stream, int *accum, int *count, int *stalls, int *resets, int *skips);
+extern void read_stream_skip_block(ReadStream *stream);
+
 #endif							/* READ_STREAM_H */

Reply via email to