Does Postgres need to fetch offset tuples from the heap
Solution 1:
It fetches them all from the heap. After setting abalance to a random value and indexing it, I restarted PostgreSQL to clear the shared_buffers, and did this (with 2,000,000 tuples):
explain (analyze , buffers ) select * from pgbench_accounts order by abalance desc limit 10 offset 100;
getting:
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=9.90..10.85 rows=10 width=97) (actual time=15.247..15.384 rows=10 loops=1)
Buffers: shared hit=1 read=114 dirtied=1
I/O Timings: read=15.088
-> Index Scan Backward using pgbench_accounts_abalance_idx on pgbench_accounts (cost=0.43..189448.93 rows=2000000 width=97) (actual time=0.113..15.363 rows=110 loops=1)
Buffers: shared hit=1 read=114 dirtied=1
I/O Timings: read=15.088
Planning:
Buffers: shared hit=44 read=4 dirtied=1
I/O Timings: read=0.173
Planning Time: 4.414 ms
Execution Time: 15.493 ms
The 114 buffers it had to read can only be explained as 110 heap tuples, plus a few pages for the index.