From 61cc443443c2126dd2232e13f68f541166af5ddc Mon Sep 17 00:00:00 2001 From: Claudio Freire Date: Tue, 28 Mar 2017 22:40:39 -0300 Subject: [PATCH 2/2] Vacuum: free dead tuples array as early as possible Allow other parts of the system to benefit from the possibly large amount of memory reserved for dead tuples after they're no longer necessary. While the memory would be freed when the command finishes, it can sometimes be some considerable time between the time vacuum is done with the array until the command finishes - mostly due to truncate taking a long time. --- src/backend/commands/vacuumlazy.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c index 4f0cf1b..d82aa7c 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -213,6 +213,7 @@ static void lazy_space_alloc(LVRelStats *vacrelstats, BlockNumber relblocks); static void lazy_record_dead_tuple(LVRelStats *vacrelstats, ItemPointer itemptr); static void lazy_clear_dead_tuples(LVRelStats *vacrelstats); +static void lazy_free_dead_tuples(LVRelStats *vacrelstats); static bool lazy_tid_reaped(ItemPointer itemptr, void *state); static inline int vac_cmp_itemptr(const void *left, const void *right); static bool heap_page_is_all_visible(Relation rel, Buffer buf, @@ -1368,6 +1369,9 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats, pgstat_progress_update_param(PROGRESS_VACUUM_PHASE, PROGRESS_VACUUM_PHASE_INDEX_CLEANUP); + /* dead tuples no longer needed past this point */ + lazy_free_dead_tuples(vacrelstats); + /* Do post-vacuum cleanup and statistics update for each index */ for (i = 0; i < nindexes; i++) lazy_cleanup_index(Irel[i], indstats[i], vacrelstats); @@ -2193,6 +2197,25 @@ lazy_clear_dead_tuples(LVRelStats *vacrelstats) } /* + * lazy_free_dead_tuples - reset all dead tuples segments + * and free all allocated memory + */ +static void +lazy_free_dead_tuples(LVRelStats *vacrelstats) +{ + int nseg; + + for (nseg = 0; nseg < vacrelstats->dead_tuples.num_segs; nseg++) + pfree(vacrelstats->dead_tuples.dt_segments[nseg].dt_tids); + if (vacrelstats->dead_tuples.dt_segments != NULL) + pfree(vacrelstats->dead_tuples.dt_segments); + vacrelstats->dead_tuples.last_seg = 0; + vacrelstats->dead_tuples.num_segs = 0; + vacrelstats->dead_tuples.num_entries = 0; + vacrelstats->dead_tuples.dt_segments = NULL; +} + +/* * lazy_tid_reaped() -- is a particular tid deletable? * * This has the right signature to be an IndexBulkDeleteCallback. -- 1.8.4.5