Re: index prefetching
Tomas Vondra <tomas.vondra@enterprisedb.com>
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
Attachments
- index-prefetch.pdf (application/pdf)
- 0001-v5-20231012.patch (text/x-patch) patch v5-0001
- 0002-comments-and-minor-cleanup-20231012.patch (text/x-patch) patch 0002
- 0003-remove-prefetch_reset-20231012.patch (text/x-patch) patch 0003
- 0004-PoC-prefetch-for-IOS-20231012.patch (text/x-patch) patch 0004
Hi, Attached is a v6 of the patch, which rebases v5 (just some minor bitrot), and also does a couple changes which I kept in separate patches to make it obvious what changed. 0001-v5-20231016.patch ---------------------- Rebase to current master. 0002-comments-and-minor-cleanup-20231012.patch ---------------------------------------------- Various comment improvements (remove obsolete ones clarify a bunch of other comments, etc.). I tried to explain the reasoning why some places disable prefetching (e.g. in catalogs, replication, ...), explain how the caching / LRU works etc. 0003-remove-prefetch_reset-20231016.patch ----------------------------------------- I decided to remove the separate prefetch_reset parameter, so that all the index_beginscan() methods only take a parameter specifying the maximum prefetch target. The reset was added early when the prefetch happened much lower in the AM code, at the index page level, and the reset was when moving to the next index page. But now after the prefetch moved to the executor, this doesn't make much sense - the resets happen on rescans, and it seems right to just reset to 0 (just like for bitmap heap scans). 0004-PoC-prefetch-for-IOS-20231016.patch ---------------------------------------- This is a PoC adding the prefetch to index-only scans too. At first that may seem rather strange, considering eliminating the heap fetches is the whole point of IOS. But if the pages are not marked as all-visible (say, the most recent part of the table), we may still have to fetch them. In which case it'd be easy to see cases that IOS is slower than a regular index scan (with prefetching). The code is quite rough. It adds a separate index_getnext_tid_prefetch() function, adding prefetching on top of index_getnext_tid(). I'm not sure it's the right pattern, but it's pretty much what index_getnext_slot() does too, except that it also does the fetch + store to the slot. Note: There's a second patch adding index-only filters, which requires the regular index scans from index_getnext_slot() to _tid() too. The prefetching then happens only after checking the visibility map (if requested). This part definitely needs improvements - for example there's no attempt to reuse the VM buffer, which I guess might be expensive. index-prefetch.pdf ------------------ Attached is also a PDF with results of the same benchmark I did before, comparing master vs. patched with various data patterns and scan types. It's not 100% comparable to earlier results as I only ran it on a laptop, and it's a bit noisier too. The overall behavior and conclusions are however the same. I was specifically interested in the IOS behavior, so I added two more cases to test - indexonlyscan and indexonlyscan-clean. The first is the worst-case scenario, with no pages marked as all-visible in VM (the test simply deletes the VM), while indexonlyscan-clean is the good-case (no heap fetches needed). The results mostly match the expected behavior, particularly for the uncached runs (when the data is expected to not be in memory): * indexonlyscan (i.e. bad case) - About the same results as "indexscans", with the same speedups etc. Which is a good thing (i.e. IOS is not unexpectedly slower than regular indexscans). * indexonlyscan-clean (i.e. good case) - Seems to have mostly the same performance as without the prefetching, except for the low-cardinality runs with many rows per key. I haven't checked what's causing this, but I'd bet it's the extra buffer lookups/management I mentioned. I noticed there's another prefetching-related patch [1] from Thomas Munro. I haven't looked at it yet, so hard to say how much it interferes with this patch. But the idea looks interesting. [1] https://www.postgresql.org/message-id/flat/CA+hUKGJkOiOCa+mag4BF+zHo7qo=o9CFheB8=g6uT5TUm2gkvA@mail.gmail.com regards -- Tomas Vondra EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company