From 0a980794c90973383e5a63f64839616a79542260 Mon Sep 17 00:00:00 2001 From: Claudio Freire Date: Thu, 8 Feb 2018 12:39:15 -0300 Subject: [PATCH 2/2] Vacuum: do a partial FSM vacuum at the beginning A partial FSM vacuum right at the start of the vacuum process helps ameliorate issues with cancelled autovacuums never updating the FSM. --- src/backend/commands/vacuumlazy.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c index 9ad0f34..2965204 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -103,6 +103,19 @@ */ #define PREFETCH_SIZE ((BlockNumber) 32) +/* + * If autovacuums get regularly cancelled, the FSM may never be + * vacuumed. To work around that, we perform an initial partial + * FSM vacuum at the beginning of the vacuum process, to quickly + * make existing unmarked free space visible. To avoid useless + * redundant work, however, we avoid recursing into branches + * that already have a set amount of free space, we only try + * to discover unmarked free space. This value controls how + * much free space is enough free space in that context. The + * value is in the terms of the FSM map. + */ +#define INITIAL_PARTIAL_FSM_VACUUM_THRESHOLD 64 + typedef struct LVRelStats { /* hasindex = true means two-pass strategy; false means one-pass */ @@ -250,6 +263,17 @@ lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params, vacrelstats->pages_removed = 0; vacrelstats->lock_waiter_detected = false; + /* + * Vacuum the Free Space Map partially before we start. + * If an earlier vacuum was canceled, and that's likely in + * highly contended tables, we may need to finish up. If we do + * it now, we make the space visible to other backends regardless + * of whether we succeed in finishing this time around. + * Don't bother checking branches that already have usable space, + * though. + */ + FreeSpaceMapVacuum(onerel, INITIAL_PARTIAL_FSM_VACUUM_THRESHOLD); + /* Open all indexes of the relation */ vac_open_indexes(onerel, RowExclusiveLock, &nindexes, &Irel); vacrelstats->hasindex = (nindexes > 0); -- 1.8.4.5