Hi Hackers, Analyzed the problem and created a patch to resolve it.
# Problem 1 When you create a foreign key to a partitioned table, referential integrity function is created for the number of partitions. Internally, SPI_prepare() creates a plan and SPI_keepplan() caches the plan. The more partitions in the referencing table, the more plans will be cached. # Problem 2 When referenced table is partitioned table, the larger the number of partitions, the larger the plan size to be cached. The actual plan processed is simple and small if pruning is enabled. However, the cached plan will include all partition information. The more partitions in the referenced table, the larger the plan size to be cached. # Idea for solution Constraints with the same pg_constraint.parentid can be combined into one plan with the same comparentid if we can guarantee that all their contents are the same. Problem 1 can be solved and significant memory bloat can be avoided. CachedPlan: 710MB -> 1466kB Solving Problem 2 could also reduce memory, but I don't have a good idea. Currently, DISCARD ALL does not discard CachedPlan by SPI as in this case. It may be possible to modify DISCARD ALL to discard CachedPlan and run it periodically. However, we think the burden on the user is high. # result with patch(PG14 HEAD(e522024b) + patch) name | bytes | pg_size_pretty ------------------+---------+---------------- CachedPlanQuery | 12912 | 13 kB CachedPlanSource | 17448 | 17 kB CachedPlan | 1501192 | 1466 kB CachedPlan * 1 Record postgres=# SELECT count(*) FROM pg_backend_memory_contexts WHERE name = 'CachedPlan' AND ident LIKE 'SELECT 1 FROM%'; count ------- 1 postgres=# SELECT * FROM pg_backend_memory_contexts WHERE name = 'CachedPlan' AND ident LIKE 'SELECT 1 FROM%'; -[ RECORD 1 ]-+-------------------------------------------------------------------------------------- name | CachedPlan ident | SELECT 1 FROM "public"."ps" x WHERE "c1" OPERATOR(pg_catalog.=) $1 FOR KEY SHARE OF x parent | CacheMemoryContext level | 2 total_bytes | 2101248 total_nblocks | 12 free_bytes | 613256 free_chunks | 1 used_bytes | 1487992 (1 record) # result without patch(PG14 HEAD(e522024b)) name | bytes | pg_size_pretty ------------------+-----------+---------------- CachedPlanQuery | 1326280 | 1295 kB CachedPlanSource | 1474528 | 1440 kB CachedPlan | 744009200 | 710 MB CachedPlan * 500 Records postgres=# SELECT count(*) FROM pg_backend_memory_contexts WHERE name = 'CachedPlan' AND ident LIKE 'SELECT 1 FROM%'; count ------- 500 SELECT * FROM pg_backend_memory_contexts WHERE name = 'CachedPlan' AND ident LIKE 'SELECT 1 FROM%'; name | CachedPlan ident | SELECT 1 FROM "public"."ps" x WHERE "c1" OPERATOR(pg_catalog.=) $1 FOR KEY SHARE OF x parent | CacheMemoryContext level | 2 total_bytes | 2101248 total_nblocks | 12 free_bytes | 613256 free_chunks | 1 used_bytes | 1487992 ...(500 same records) Best Regards, -- Keisuke Kuroda NTT Software Innovation Center keisuke.kuroda.3...@gmail.com
v1_reduce_ri_SPI-plan-hash.patch
Description: Binary data