From 227cdaa3910fac015a3d395a01c2eeb13e346072 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 | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c index 287accd..1d2b18f 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -212,6 +212,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 bool heap_page_is_all_visible(Relation rel, Buffer buf, TransactionId *visibility_cutoff_xid, bool *all_frozen); @@ -1373,6 +1374,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); @@ -2200,6 +2204,27 @@ 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 < GetNumDeadTuplesSegments(vacrelstats); nseg++) + if (GetDeadTuplesSegment(vacrelstats, nseg)->dt_tids != NULL) + pfree(GetDeadTuplesSegment(vacrelstats, nseg)->dt_tids); + if (vacrelstats->dead_tuples.dt_segments != NULL) + 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; +} + +/* * vac_itemptr_binsrch() -- search a sorted array of item pointers * * Returns the offset of the first item pointer greater than or -- 1.8.4.5