Hi, On 2021-05-11 19:02:00 -0700, Andres Freund wrote: > Why would rebuilding non-accessed relcache entries over and over help > with that? I am not proposing that we do not mark all cache entries are > invalid, or that we do not rebuild tables that aren't accessed.
A slightly more concrete proposal: We introduce a new list of pending relcache invalidations. When RelationCacheInvalidateEntry() or RelationCacheInvalidateEntry() invalidate an entry, it gets put on that list (pretty much like the existing rebuildList in RelationCacheInvalidate(), except longer lived). When an invalid relcache entry is accessed, it is obviously immediately rebuilt. Normally RelationCacheInvalidate() eagerly processes that list, as well as in ProcessInvalidationMessages(), ReceiveSharedInvalidMessages() etc. But SearchCatCacheMiss() sets a flag that prevents the eager processing in RelationCacheInvalidate() - that avoids needing to rebuild relcache entries that aren't actually accessed as part of a cache miss repeatedly. I think just avoiding the repeated relcache rebuilds in SearchCatCacheMiss() would reduce runtime significantly, even if SearchCatCacheMiss() at the end would process that list of relcache invalidations. But I think it might not even be needed to achieve good coverage? It might be fine to defer processing of the pending list until the next RelationCacheInvalidate() triggered by a relation_open() outside of a catcache miss (or obviously until it is accessed next)? I think this scheme wouldn't just improve CCI performance, but importantly also normal invalidation processing. Right now we'll often re-build the same cache entry multiple times as part of a single ReceiveSharedInvalidMessages() as it's pretty common that a relation is the target of DDL in very close-by transactions. Greetings, Andres Freund