nbtree's _bt_first function uses arrays on the stack to store the scan keys that will be used for initial positioning purposes. We could use dynamic allocation here instead, but experience has shown that that would cause performance issues -- particularly during nestloop joins with an inner index scan. The amount of stack space used by _bt_first does still seem kind of excessive, though.
Perhaps most notably, "BTScanInsertData inskey" takes up 2328 bytes. There isn't much we can do about that, unless we're willing to make _bt_first more complicated. The "inskey" variable is so large because it ends with an array of INDEX_MAX_KEYS-many (generally 32) ScanKeyData structs -- these structs are themselves fairly large struct (they're 72 bytes each). However, there's no reason why "ScanKeyData notnullkeys[INDEX_MAX_KEYS]" needs to be an array at all. In practice, _bt_first will only need a single temp notnullkeys ScanKeyData, since there can never be more than a single deduced NOT NULL constraint used within our final insertion scan key. Attached patch shows how this could work. It saves us a little over 2 KiB of stack space, which seems worthwhile given that the patch is so simple. I'll submit this patch to the next open commitfest for Postgres 19. -- Peter Geoghegan
v1-0001-nbtree-Use-only-one-notnullkey-ScanKeyData.patch
Description: Binary data