postgres.git / summary / log / commit / refs

commit    16d394c05065d93b2ceca5b9be8dfc608193043a
Author:   Tomas Vondra <tomas.vondra@postgresql.org>
Date:     Mon Sep 20 23:14:11 2021 +0000
First released in: 15.0, 10.19, 11.14, 12.9, 13.5, 14.0

    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 | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/backend/statistics/extended_stats.c b/src/backend/statistics/extended_stats.c index 8951543b7eb..e0aece6b51d 100644 --- a/src/backend/statistics/extended_stats.c +++ b/src/backend/statistics/extended_stats.c @@ -90,14 +90,15 @@ BuildRelationExtStatistics(Relation onerel, double totalrows, MemoryContext cxt; MemoryContext oldcxt; + pg_stext = table_open(StatisticExtRelationId, RowExclusiveLock); + stats = fetch_statentries_for_relation(pg_stext, RelationGetRelid(onerel)); + + /* memory context for building each statistics object */ cxt = AllocSetContextCreate(CurrentMemoryContext, "BuildRelationExtStatistics", ALLOCSET_DEFAULT_SIZES); oldcxt = MemoryContextSwitchTo(cxt); - pg_stext = table_open(StatisticExtRelationId, RowExclusiveLock); - stats = fetch_statentries_for_relation(pg_stext, RelationGetRelid(onerel)); - foreach(lc, stats) { StatExtEntry *stat = (StatExtEntry *) lfirst(lc); @@ -148,12 +149,17 @@ BuildRelationExtStatistics(Relation onerel, double totalrows, /* store the statistics in the catalog */ statext_store(stat->statOid, ndistinct, dependencies, mcv, stats); - } - table_close(pg_stext, RowExclusiveLock); + /* free the data used for building this statistics object */ + MemoryContextReset(cxt); + } MemoryContextSwitchTo(oldcxt); MemoryContextDelete(cxt); + + list_free(stats); + + table_close(pg_stext, RowExclusiveLock); } /* [parent: 76001de031a5]