mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
During VACUUM FULL, truncate off any deletable pages that are at the
end of a btree index. This isn't super-effective, since we won't move nondeletable pages, but it's better than nothing. Also, improve stats displayed during VACUUM VERBOSE.
This commit is contained in:
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.100 2003/02/22 00:45:03 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.101 2003/02/24 00:57:17 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1648,11 +1648,10 @@ gistbulkdelete(PG_FUNCTION_ARGS)
|
|||||||
/* return statistics */
|
/* return statistics */
|
||||||
num_pages = RelationGetNumberOfBlocks(rel);
|
num_pages = RelationGetNumberOfBlocks(rel);
|
||||||
|
|
||||||
result = (IndexBulkDeleteResult *) palloc(sizeof(IndexBulkDeleteResult));
|
result = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
|
||||||
result->num_pages = num_pages;
|
result->num_pages = num_pages;
|
||||||
result->num_index_tuples = num_index_tuples;
|
result->num_index_tuples = num_index_tuples;
|
||||||
result->tuples_removed = tuples_removed;
|
result->tuples_removed = tuples_removed;
|
||||||
result->pages_free = 0;
|
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.61 2003/02/22 00:45:03 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.62 2003/02/24 00:57:17 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* This file contains only the public interface routines.
|
* This file contains only the public interface routines.
|
||||||
@ -489,11 +489,10 @@ hashbulkdelete(PG_FUNCTION_ARGS)
|
|||||||
/* return statistics */
|
/* return statistics */
|
||||||
num_pages = RelationGetNumberOfBlocks(rel);
|
num_pages = RelationGetNumberOfBlocks(rel);
|
||||||
|
|
||||||
result = (IndexBulkDeleteResult *) palloc(sizeof(IndexBulkDeleteResult));
|
result = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
|
||||||
result->num_pages = num_pages;
|
result->num_pages = num_pages;
|
||||||
result->num_index_tuples = num_index_tuples;
|
result->num_index_tuples = num_index_tuples;
|
||||||
result->tuples_removed = tuples_removed;
|
result->tuples_removed = tuples_removed;
|
||||||
result->pages_free = 0;
|
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.99 2003/02/23 23:27:21 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.100 2003/02/24 00:57:17 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -24,6 +24,7 @@
|
|||||||
#include "catalog/index.h"
|
#include "catalog/index.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "storage/freespace.h"
|
#include "storage/freespace.h"
|
||||||
|
#include "storage/smgr.h"
|
||||||
|
|
||||||
|
|
||||||
/* Working state for btbuild and its callback */
|
/* Working state for btbuild and its callback */
|
||||||
@ -673,11 +674,10 @@ btbulkdelete(PG_FUNCTION_ARGS)
|
|||||||
/* return statistics */
|
/* return statistics */
|
||||||
num_pages = RelationGetNumberOfBlocks(rel);
|
num_pages = RelationGetNumberOfBlocks(rel);
|
||||||
|
|
||||||
result = (IndexBulkDeleteResult *) palloc(sizeof(IndexBulkDeleteResult));
|
result = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
|
||||||
result->num_pages = num_pages;
|
result->num_pages = num_pages;
|
||||||
result->num_index_tuples = num_index_tuples;
|
result->num_index_tuples = num_index_tuples;
|
||||||
result->tuples_removed = tuples_removed;
|
result->tuples_removed = tuples_removed;
|
||||||
result->pages_free = 0; /* not computed here */
|
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
@ -746,6 +746,12 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
|
|||||||
pageSpaces[nFreePages].avail = BLCKSZ-1;
|
pageSpaces[nFreePages].avail = BLCKSZ-1;
|
||||||
nFreePages++;
|
nFreePages++;
|
||||||
}
|
}
|
||||||
|
pages_deleted++;
|
||||||
|
}
|
||||||
|
else if (P_ISDELETED(opaque))
|
||||||
|
{
|
||||||
|
/* Already deleted, but can't recycle yet */
|
||||||
|
pages_deleted++;
|
||||||
}
|
}
|
||||||
else if ((opaque->btpo_flags & BTP_HALF_DEAD) ||
|
else if ((opaque->btpo_flags & BTP_HALF_DEAD) ||
|
||||||
P_FIRSTDATAKEY(opaque) > PageGetMaxOffsetNumber(page))
|
P_FIRSTDATAKEY(opaque) > PageGetMaxOffsetNumber(page))
|
||||||
@ -758,7 +764,10 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
|
|||||||
oldcontext = MemoryContextSwitchTo(mycontext);
|
oldcontext = MemoryContextSwitchTo(mycontext);
|
||||||
|
|
||||||
ndel = _bt_pagedel(rel, buf, info->vacuum_full);
|
ndel = _bt_pagedel(rel, buf, info->vacuum_full);
|
||||||
pages_deleted += ndel;
|
|
||||||
|
/* count only this page, else may double-count parent */
|
||||||
|
if (ndel)
|
||||||
|
pages_deleted++;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* During VACUUM FULL it's okay to recycle deleted pages
|
* During VACUUM FULL it's okay to recycle deleted pages
|
||||||
@ -786,6 +795,50 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
|
|||||||
_bt_relbuf(rel, buf);
|
_bt_relbuf(rel, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* During VACUUM FULL, we truncate off any recyclable pages at the
|
||||||
|
* end of the index. In a normal vacuum it'd be unsafe to do this
|
||||||
|
* except by acquiring exclusive lock on the index and then rechecking
|
||||||
|
* all the pages; doesn't seem worth it.
|
||||||
|
*/
|
||||||
|
if (info->vacuum_full && nFreePages > 0)
|
||||||
|
{
|
||||||
|
BlockNumber new_pages = num_pages;
|
||||||
|
|
||||||
|
while (nFreePages > 0 &&
|
||||||
|
pageSpaces[nFreePages-1].blkno == new_pages-1)
|
||||||
|
{
|
||||||
|
new_pages--;
|
||||||
|
pages_deleted--;
|
||||||
|
nFreePages--;
|
||||||
|
}
|
||||||
|
if (new_pages != num_pages)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Okay to truncate.
|
||||||
|
*
|
||||||
|
* First, flush any shared buffers for the blocks we intend to
|
||||||
|
* delete. FlushRelationBuffers is a bit more than we need for
|
||||||
|
* this, since it will also write out dirty buffers for blocks we
|
||||||
|
* aren't deleting, but it's the closest thing in bufmgr's API.
|
||||||
|
*/
|
||||||
|
i = FlushRelationBuffers(rel, new_pages);
|
||||||
|
if (i < 0)
|
||||||
|
elog(ERROR, "btvacuumcleanup: FlushRelationBuffers returned %d",
|
||||||
|
i);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do the physical truncation.
|
||||||
|
*/
|
||||||
|
new_pages = smgrtruncate(DEFAULT_SMGR, rel, new_pages);
|
||||||
|
rel->rd_nblocks = new_pages; /* update relcache immediately */
|
||||||
|
rel->rd_targblock = InvalidBlockNumber;
|
||||||
|
num_pages = new_pages;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update the shared Free Space Map with the info we now have about
|
* Update the shared Free Space Map with the info we now have about
|
||||||
* free space in the index, discarding any old info the map may have.
|
* free space in the index, discarding any old info the map may have.
|
||||||
@ -797,13 +850,9 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
MemoryContextDelete(mycontext);
|
MemoryContextDelete(mycontext);
|
||||||
|
|
||||||
if (pages_deleted > 0)
|
|
||||||
elog(info->message_level, "Index %s: %u pages, deleted %u; %u now free",
|
|
||||||
RelationGetRelationName(rel),
|
|
||||||
num_pages, pages_deleted, nFreePages);
|
|
||||||
|
|
||||||
/* update statistics */
|
/* update statistics */
|
||||||
stats->num_pages = num_pages;
|
stats->num_pages = num_pages;
|
||||||
|
stats->pages_deleted = pages_deleted;
|
||||||
stats->pages_free = nFreePages;
|
stats->pages_free = nFreePages;
|
||||||
|
|
||||||
PG_RETURN_POINTER(stats);
|
PG_RETURN_POINTER(stats);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.76 2003/02/22 00:45:04 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.77 2003/02/24 00:57:17 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1248,11 +1248,10 @@ rtbulkdelete(PG_FUNCTION_ARGS)
|
|||||||
/* return statistics */
|
/* return statistics */
|
||||||
num_pages = RelationGetNumberOfBlocks(rel);
|
num_pages = RelationGetNumberOfBlocks(rel);
|
||||||
|
|
||||||
result = (IndexBulkDeleteResult *) palloc(sizeof(IndexBulkDeleteResult));
|
result = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
|
||||||
result->num_pages = num_pages;
|
result->num_pages = num_pages;
|
||||||
result->num_index_tuples = num_index_tuples;
|
result->num_index_tuples = num_index_tuples;
|
||||||
result->tuples_removed = tuples_removed;
|
result->tuples_removed = tuples_removed;
|
||||||
result->pages_free = 0;
|
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.249 2003/02/23 20:32:12 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.250 2003/02/24 00:57:17 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -2626,9 +2626,10 @@ scan_index(Relation indrel, double num_tuples)
|
|||||||
stats->num_pages, stats->num_index_tuples,
|
stats->num_pages, stats->num_index_tuples,
|
||||||
false);
|
false);
|
||||||
|
|
||||||
elog(elevel, "Index %s: Pages %u, %u free; Tuples %.0f.\n\t%s",
|
elog(elevel, "Index %s: Pages %u, %u deleted, %u free; Tuples %.0f.\n\t%s",
|
||||||
RelationGetRelationName(indrel),
|
RelationGetRelationName(indrel),
|
||||||
stats->num_pages, stats->pages_free, stats->num_index_tuples,
|
stats->num_pages, stats->pages_deleted, stats->pages_free,
|
||||||
|
stats->num_index_tuples,
|
||||||
vac_show_rusage(&ru0));
|
vac_show_rusage(&ru0));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2687,9 +2688,9 @@ vacuum_index(VacPageList vacpagelist, Relation indrel,
|
|||||||
stats->num_pages, stats->num_index_tuples,
|
stats->num_pages, stats->num_index_tuples,
|
||||||
false);
|
false);
|
||||||
|
|
||||||
elog(elevel, "Index %s: Pages %u, %u free; Tuples %.0f: Deleted %.0f.\n\t%s",
|
elog(elevel, "Index %s: Pages %u, %u deleted, %u free; Tuples %.0f: Deleted %.0f.\n\t%s",
|
||||||
RelationGetRelationName(indrel),
|
RelationGetRelationName(indrel),
|
||||||
stats->num_pages, stats->pages_free,
|
stats->num_pages, stats->pages_deleted, stats->pages_free,
|
||||||
stats->num_index_tuples - keep_tuples, stats->tuples_removed,
|
stats->num_index_tuples - keep_tuples, stats->tuples_removed,
|
||||||
vac_show_rusage(&ru0));
|
vac_show_rusage(&ru0));
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.25 2003/02/23 20:32:12 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.26 2003/02/24 00:57:17 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -586,9 +586,10 @@ lazy_scan_index(Relation indrel, LVRelStats *vacrelstats)
|
|||||||
stats->num_pages, stats->num_index_tuples,
|
stats->num_pages, stats->num_index_tuples,
|
||||||
false);
|
false);
|
||||||
|
|
||||||
elog(elevel, "Index %s: Pages %u, %u free; Tuples %.0f.\n\t%s",
|
elog(elevel, "Index %s: Pages %u, %u deleted, %u free; Tuples %.0f.\n\t%s",
|
||||||
RelationGetRelationName(indrel),
|
RelationGetRelationName(indrel),
|
||||||
stats->num_pages, stats->pages_free, stats->num_index_tuples,
|
stats->num_pages, stats->pages_deleted, stats->pages_free,
|
||||||
|
stats->num_index_tuples,
|
||||||
vac_show_rusage(&ru0));
|
vac_show_rusage(&ru0));
|
||||||
|
|
||||||
pfree(stats);
|
pfree(stats);
|
||||||
@ -641,9 +642,9 @@ lazy_vacuum_index(Relation indrel, LVRelStats *vacrelstats)
|
|||||||
stats->num_pages, stats->num_index_tuples,
|
stats->num_pages, stats->num_index_tuples,
|
||||||
false);
|
false);
|
||||||
|
|
||||||
elog(elevel, "Index %s: Pages %u, %u free; Tuples %.0f: Deleted %.0f.\n\t%s",
|
elog(elevel, "Index %s: Pages %u, %u deleted, %u free; Tuples %.0f: Deleted %.0f.\n\t%s",
|
||||||
RelationGetRelationName(indrel),
|
RelationGetRelationName(indrel),
|
||||||
stats->num_pages, stats->pages_free,
|
stats->num_pages, stats->pages_deleted, stats->pages_free,
|
||||||
stats->num_index_tuples, stats->tuples_removed,
|
stats->num_index_tuples, stats->tuples_removed,
|
||||||
vac_show_rusage(&ru0));
|
vac_show_rusage(&ru0));
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: genam.h,v 1.38 2003/02/22 00:45:05 tgl Exp $
|
* $Id: genam.h,v 1.39 2003/02/24 00:57:17 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -34,7 +34,8 @@ typedef struct IndexBulkDeleteResult
|
|||||||
BlockNumber num_pages; /* pages remaining in index */
|
BlockNumber num_pages; /* pages remaining in index */
|
||||||
double num_index_tuples; /* tuples remaining */
|
double num_index_tuples; /* tuples remaining */
|
||||||
double tuples_removed; /* # removed by bulk-delete operation */
|
double tuples_removed; /* # removed by bulk-delete operation */
|
||||||
BlockNumber pages_free; /* # unused pages in index */
|
BlockNumber pages_deleted; /* # unused pages in index */
|
||||||
|
BlockNumber pages_free; /* # pages available for reuse */
|
||||||
} IndexBulkDeleteResult;
|
} IndexBulkDeleteResult;
|
||||||
|
|
||||||
/* Typedef for callback function to determine if a tuple is bulk-deletable */
|
/* Typedef for callback function to determine if a tuple is bulk-deletable */
|
||||||
|
Reference in New Issue
Block a user