From 9e936693a9fc464511b52b14fb681cdea014bf59 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 21 Sep 2006 20:31:22 +0000 Subject: Fix free space map to correctly track the total amount of FSM space needed even when a single relation requires more than max_fsm_pages pages. Also, make VACUUM emit a warning in this case, since it likely means that VACUUM FULL or other drastic corrective measure is needed. Per reports from Jeff Frost and others of unexpected changes in the claimed max_fsm_pages need. --- src/backend/access/gin/ginvacuum.c | 14 ++++++++------ src/backend/access/gist/gistvacuum.c | 20 ++++++++++---------- src/backend/access/nbtree/nbtree.c | 16 +++++++++++----- 3 files changed, 29 insertions(+), 21 deletions(-) (limited to 'src/backend/access') diff --git a/src/backend/access/gin/ginvacuum.c b/src/backend/access/gin/ginvacuum.c index 2bc80a26433..31e5f647f07 100644 --- a/src/backend/access/gin/ginvacuum.c +++ b/src/backend/access/gin/ginvacuum.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/gin/ginvacuum.c,v 1.5 2006/07/31 20:08:59 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/gin/ginvacuum.c,v 1.6 2006/09/21 20:31:21 tgl Exp $ *------------------------------------------------------------------------- */ @@ -575,7 +575,8 @@ ginvacuumcleanup(PG_FUNCTION_ARGS) { bool needLock; BlockNumber npages, blkno; - BlockNumber nFreePages, + BlockNumber totFreePages, + nFreePages, *freePages, maxFreePages; BlockNumber lastBlock = GIN_ROOT_BLKNO, @@ -610,7 +611,7 @@ ginvacuumcleanup(PG_FUNCTION_ARGS) { if (maxFreePages > MaxFSMPages) maxFreePages = MaxFSMPages; - nFreePages = 0; + totFreePages = nFreePages = 0; freePages = (BlockNumber *) palloc(sizeof(BlockNumber) * maxFreePages); for (blkno = GIN_ROOT_BLKNO + 1; blkno < npages; blkno++) { @@ -626,6 +627,7 @@ ginvacuumcleanup(PG_FUNCTION_ARGS) { if ( GinPageIsDeleted(page) ) { if (nFreePages < maxFreePages) freePages[nFreePages++] = blkno; + totFreePages++; } else lastFilledBlock = blkno; @@ -638,7 +640,7 @@ ginvacuumcleanup(PG_FUNCTION_ARGS) { int i; for (i = 0; i < nFreePages; i++) if (freePages[i] >= lastFilledBlock) { - nFreePages = i; + totFreePages = nFreePages = i; break; } @@ -648,8 +650,8 @@ ginvacuumcleanup(PG_FUNCTION_ARGS) { stats->pages_removed = lastBlock - lastFilledBlock; } - RecordIndexFreeSpace(&index->rd_node, nFreePages, freePages); - stats->pages_free = nFreePages; + RecordIndexFreeSpace(&index->rd_node, totFreePages, nFreePages, freePages); + stats->pages_free = totFreePages; if (needLock) LockRelationForExtension(index, ExclusiveLock); diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c index 37b5631b281..e5c73c8c224 100644 --- a/src/backend/access/gist/gistvacuum.c +++ b/src/backend/access/gist/gistvacuum.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.26 2006/07/31 20:08:59 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.27 2006/09/21 20:31:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -491,7 +491,8 @@ gistvacuumcleanup(PG_FUNCTION_ARGS) Relation rel = info->index; BlockNumber npages, blkno; - BlockNumber nFreePages, + BlockNumber totFreePages, + nFreePages, *freePages, maxFreePages; BlockNumber lastBlock = GIST_ROOT_BLKNO, @@ -563,8 +564,9 @@ gistvacuumcleanup(PG_FUNCTION_ARGS) if (maxFreePages > MaxFSMPages) maxFreePages = MaxFSMPages; - nFreePages = 0; + totFreePages = nFreePages = 0; freePages = (BlockNumber *) palloc(sizeof(BlockNumber) * maxFreePages); + for (blkno = GIST_ROOT_BLKNO + 1; blkno < npages; blkno++) { Buffer buffer; @@ -579,10 +581,8 @@ gistvacuumcleanup(PG_FUNCTION_ARGS) if (PageIsNew(page) || GistPageIsDeleted(page)) { if (nFreePages < maxFreePages) - { - freePages[nFreePages] = blkno; - nFreePages++; - } + freePages[nFreePages++] = blkno; + totFreePages++; } else lastFilledBlock = blkno; @@ -597,7 +597,7 @@ gistvacuumcleanup(PG_FUNCTION_ARGS) for (i = 0; i < nFreePages; i++) if (freePages[i] >= lastFilledBlock) { - nFreePages = i; + totFreePages = nFreePages = i; break; } @@ -606,11 +606,11 @@ gistvacuumcleanup(PG_FUNCTION_ARGS) stats->std.pages_removed = lastBlock - lastFilledBlock; } - RecordIndexFreeSpace(&rel->rd_node, nFreePages, freePages); + RecordIndexFreeSpace(&rel->rd_node, totFreePages, nFreePages, freePages); pfree(freePages); /* return statistics */ - stats->std.pages_free = nFreePages; + stats->std.pages_free = totFreePages; if (needLock) LockRelationForExtension(rel, ExclusiveLock); stats->std.num_pages = RelationGetNumberOfBlocks(rel); diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index c58974cca13..fa5b162c908 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -12,7 +12,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.150 2006/08/24 01:18:34 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.151 2006/09/21 20:31:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,8 +53,9 @@ typedef struct void *callback_state; BTCycleId cycleid; BlockNumber *freePages; - int nFreePages; - int maxFreePages; + int nFreePages; /* number of entries in freePages[] */ + int maxFreePages; /* allocated size of freePages[] */ + BlockNumber totFreePages; /* true total # of free pages */ MemoryContext pagedelcontext; } BTVacState; @@ -636,6 +637,7 @@ btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, vstate.freePages = NULL; /* temporarily */ vstate.nFreePages = 0; vstate.maxFreePages = 0; + vstate.totFreePages = 0; /* Create a temporary memory context to run _bt_pagedel in */ vstate.pagedelcontext = AllocSetContextCreate(CurrentMemoryContext, @@ -716,6 +718,7 @@ btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, new_pages--; stats->pages_deleted--; vstate.nFreePages--; + vstate.totFreePages = vstate.nFreePages; /* can't be more */ } if (new_pages != num_pages) { @@ -736,7 +739,8 @@ btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, * pages in the index, discarding any old info the map may have. We do not * need to sort the page numbers; they're in order already. */ - RecordIndexFreeSpace(&rel->rd_node, vstate.nFreePages, vstate.freePages); + RecordIndexFreeSpace(&rel->rd_node, vstate.totFreePages, + vstate.nFreePages, vstate.freePages); pfree(vstate.freePages); @@ -744,7 +748,7 @@ btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, /* update statistics */ stats->num_pages = num_pages; - stats->pages_free = vstate.nFreePages; + stats->pages_free = vstate.totFreePages; } /* @@ -816,6 +820,7 @@ restart: /* Okay to recycle this page */ if (vstate->nFreePages < vstate->maxFreePages) vstate->freePages[vstate->nFreePages++] = blkno; + vstate->totFreePages++; stats->pages_deleted++; } else if (P_ISDELETED(opaque)) @@ -954,6 +959,7 @@ restart: { if (vstate->nFreePages < vstate->maxFreePages) vstate->freePages[vstate->nFreePages++] = blkno; + vstate->totFreePages++; } MemoryContextSwitchTo(oldcontext); -- cgit v1.2.3