Re: unnecessary executor overheads around seqscans
| От | Heikki Linnakangas |
|---|---|
| Тема | Re: unnecessary executor overheads around seqscans |
| Дата | |
| Msg-id | 0dc565fa-bcc0-4600-9cef-263822b08132@iki.fi обсуждение исходный текст |
| Ответ на | Re: unnecessary executor overheads around seqscans (Andres Freund <andres@anarazel.de>) |
| Ответы |
Re: unnecessary executor overheads around seqscans
|
| Список | pgsql-hackers |
On 27/01/2026 01:25, Andres Freund wrote: > On 2026-01-26 17:23:16 +0200, Heikki Linnakangas wrote: >> Perhaps we should turn the ExecScanExtended() function inside out. Instead >> of passing SeqNext as a callback to ExecScanExtended(), we would have a >> function like this (for illustration purposes only, doesn't compile): > > That would be one approach, would require structural changes in a fair number > of places though :/. ExecScanExtended is only used in execScan.c and nodeSeqScan.c, so not that many places. Even replacing ExecScan() completely would be isolated to src/backend/executor. > A slightly simpler approach could be for ExecScanExtended to pass in these > parameters as arguments to the callbacks. For things like estate, direction > and scanslot, that makes plenty sense. It's a bit more problematic for the > scan descriptor, due to the "lazy start" we have in a few places. Yep, it's less flexible. We have to know beforehand which variables the function might want to avoid re-fetching, and add them all as parameters. > I very briefly prototyped that (relying on the fact that all callers cast to > the callback type and that passing unused arguments just works even if the > function definition doesn't expect them), and that seems to do the trick. This can be a very hot codepath so if we can shave a few % off, I'm willing to hold my nose. But if we can do it more elegantly, even better... > What shows up more visibly afterwards is that we set ExecScanExtended() sets > econtext->ecxt_scantuple in every iteration, despite that not changing in > almost all cases (I think for FDWs it could, fdwhandler.sgml just says that > the scanslot "should" be used). Huh, that's just a single store instruction. This really is a hot path. Or is it just that the first instruction after the function call causes some kind of a stall or data dependency, i.e. if that was removed, it'd just move to the next instruction instead? I wonder about the access to (econtext)->ecxt_per_tuple_memory. That never changes, but we're re-fetching that too on every iteration. InstrCountFiltered1() also fetches node->instrument, with a NULL check, on every iteration. Maybe keep a counter in a local variable and only call InstrCountFiltered1() when exiting the loop. I guess these don't show up in a profiler or you would've latched on them already.. - Heikki
В списке pgsql-hackers по дате отправления: