From 3aac99068cd7abe9d6fbc8c0faa361d75f7d0bfc Mon Sep 17 00:00:00 2001 From: Tomas Vondra Date: Tue, 21 Sep 2021 01:14:11 +0200 Subject: [PATCH] Free memory after building each statistics object Until now, all extended statistics on a given relation were built in the same memory context, without resetting. Some of the memory was released explicitly, but not all of it - for example memory allocated while detoasting values is hard to free. This is how it worked since extended statistics were introduced in PostgreSQL 10, but adding support for extended stats on expressions made the issue somewhat worse as it increases the number of statistics to build. Fixed by adding a memory context which gets reset after building each statistics object (all the statistics kinds included in it). Resetting it after building each statistics kind would be even better, but it would require more invasive changes and copying of results, making it harder to backpatch. Backpatch to PostgreSQL 10, where extended statistics were introduced. Author: Justin Pryzby Reported-by: Justin Pryzby Reviewed-by: Tomas Vondra Backpatch-through: 10 Discussion: https://www.postgresql.org/message-id/20210915200928.GP831%40telsasoft.com --- src/backend/statistics/extended_stats.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/backend/statistics/extended_stats.c b/src/backend/statistics/extended_stats.c index b0d0c6b205b..8cb469ceed4 100644 --- a/src/backend/statistics/extended_stats.c +++ b/src/backend/statistics/extended_stats.c @@ -74,13 +74,15 @@ BuildRelationExtStatistics(Relation onerel, double totalrows, MemoryContext cxt; MemoryContext oldcxt; - cxt = AllocSetContextCreate(CurrentMemoryContext, "stats ext", - ALLOCSET_DEFAULT_SIZES); - oldcxt = MemoryContextSwitchTo(cxt); - pg_stext = heap_open(StatisticExtRelationId, RowExclusiveLock); stats = fetch_statentries_for_relation(pg_stext, RelationGetRelid(onerel)); + /* memory context for building each statistics object */ + cxt = AllocSetContextCreate(CurrentMemoryContext, + "stats ext", + ALLOCSET_DEFAULT_SIZES); + oldcxt = MemoryContextSwitchTo(cxt); + foreach(lc, stats) { StatExtEntry *stat = (StatExtEntry *) lfirst(lc); @@ -127,12 +129,17 @@ BuildRelationExtStatistics(Relation onerel, double totalrows, /* store the statistics in the catalog */ statext_store(pg_stext, stat->statOid, ndistinct, dependencies, stats); - } - heap_close(pg_stext, RowExclusiveLock); + /* free the data used for building this statistics object */ + MemoryContextReset(cxt); + } MemoryContextSwitchTo(oldcxt); MemoryContextDelete(cxt); + + list_free(stats); + + heap_close(pg_stext, RowExclusiveLock); } /* -- 2.39.5