From 64e3c9451ec56db075d64b82ece8afaa2731cdc8 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 69fc00d..6f6c461 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -219,6 +219,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); @@ -1380,6 +1381,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); @@ -2207,6 +2211,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