Re: index prefetching
Peter Geoghegan <pg@bowt.ie>
Commits
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
aio: io_uring: Trigger async processing for large IOs
- a9ee66881744 19 (unreleased) landed
-
read stream: Split decision about look ahead for AIO and combining
- 8ca147d582a5 19 (unreleased) landed
-
read_stream: Only increase read-ahead distance when waiting for IO
- f63ca3379025 19 (unreleased) landed
-
read_stream: Prevent distance from decaying too quickly
- 6e36930f9aaf 19 (unreleased) landed
-
Reduce ExecSeqScan* code size using pg_assume()
- b227b0bb4e03 19 (unreleased) cited
-
Fix rare bug in read_stream.c's split IO handling.
- b421223172a2 19 (unreleased) cited
-
Fix multiranges to behave more like dependent types.
- 3e8235ba4f9c 17.0 cited
-
Add EXPLAIN (MEMORY) to report planner memory consumption
- 5de890e3610d 17.0 cited
-
Optimize nbtree backward scan boundary cases.
- c9c0589fda0e 17.0 cited
-
Increment xactCompletionCount during subtransaction abort.
- 90c885cdab8b 14.0 cited
-
Add nbtree Valgrind buffer lock checks.
- 4a70f829d86c 14.0 cited
-
Add nbtree high key "continuescan" optimization.
- 29b64d1de7c7 12.0 cited
-
Reduce pinning and buffer content locking for btree scans.
- 2ed5b87f96d4 9.5.0 cited
-
Teach btree to handle ScalarArrayOpExpr quals natively.
- 9e8da0f75731 9.2.0 cited
On Thu, Aug 14, 2025 at 10:12 PM Peter Geoghegan <pg@bowt.ie> wrote: > As far as I know, we only have the following unambiguous performance > regressions (that clearly need to be fixed): > > 1. This issue. > > 2. There's about a 3% loss of throughput on pgbench SELECT. Update: I managed to fix the performance regression with pgbench SELECT (regression 2). Since Andres' patch fixes the other regression (regression 1), we no longer have any known performance regression (though I don't doubt that they still exist somewhere). I've also added back the enable_indexscan_prefetch testing GUC (Andres asked me to do that a few weeks back). If you set enable_indexscan_prefetch=false, btgetbatch performance is virtually identical to master/btgettuple. A working copy of the patchset with these revisions is available from: https://github.com/petergeoghegan/postgres/tree/index-prefetch-batch-v1.6 The solution to the pgbench issue was surprisingly straightforward. Profiling showed that the regression was caused by the added overhead of using the read stream, for queries where prefetching cannot possibly help -- such small startup costs are relatively noticeable with pgbench's highly selective scans. It turns out that it's possible to initially avoid using a read stream, while still retaining the option of switching over to using a read stream later on. The trick to fixing the pgbench issue was delaying creating a read stream for long enough for the pgbench queries to never need to create one, without that impacting queries that at least have some chance of benefiting from prefetching. The actual heuristic I'm using to decide when to start the read stream is simple: only start a read stream right after the scan's second batch is returned by amgetbatch, but before we've fetched any heap blocks related to that second batch (start using a read stream when fetching new heap blocks from that second batch). It's possible that that heuristic isn't sophisticated enough for other types of queries. But either way the basic structure within indexam.c places no restrictions on when we start a read stream. It doesn't have to be aligned with amgetbatch-wise batch boundaries, for example (I just found that structure convenient). I haven't spent much time testing this change, but it appears to work perfectly (no pgbench regressions, but also no regressions in queries that were already seeing significant benefits from prefetching). I'd feel better about all this if we had better testing of the read stream invariants by (say) adding assertions to index_scan_stream_read_next, the read stream callback. And just having comments that explain those invariants. -- Peter Geoghegan