mirror of
https://github.com/postgres/postgres.git
synced 2025-07-11 10:01:57 +03:00
New-style vacuum neglected to update pg_class statistics about indexes
if there were no deletions to do.
This commit is contained in:
@ -31,7 +31,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.2 2001/07/15 22:48:17 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.3 2001/07/18 00:46:25 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -101,6 +101,7 @@ static TransactionId XmaxRecent;
|
||||
static void lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
|
||||
Relation *Irel, int nindexes);
|
||||
static void lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats);
|
||||
static void lazy_scan_index(Relation indrel, LVRelStats *vacrelstats);
|
||||
static void lazy_vacuum_index(Relation indrel, LVRelStats *vacrelstats);
|
||||
static int lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
|
||||
int tupindex, LVRelStats *vacrelstats);
|
||||
@ -113,6 +114,7 @@ static void lazy_record_dead_tuple(LVRelStats *vacrelstats,
|
||||
static void lazy_record_free_space(LVRelStats *vacrelstats,
|
||||
BlockNumber page, Size avail);
|
||||
static bool lazy_tid_reaped(ItemPointer itemptr, void *state);
|
||||
static bool dummy_tid_reaped(ItemPointer itemptr, void *state);
|
||||
static void lazy_update_fsm(Relation onerel, LVRelStats *vacrelstats);
|
||||
static int vac_cmp_itemptr(const void *left, const void *right);
|
||||
|
||||
@ -197,6 +199,7 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
|
||||
tups_vacuumed,
|
||||
nkeep,
|
||||
nunused;
|
||||
bool did_vacuum_index = false;
|
||||
int i;
|
||||
VacRUsage ru0;
|
||||
|
||||
@ -235,6 +238,7 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
|
||||
/* Remove index entries */
|
||||
for (i = 0; i < nindexes; i++)
|
||||
lazy_vacuum_index(Irel[i], vacrelstats);
|
||||
did_vacuum_index = true;
|
||||
/* Remove tuples from heap */
|
||||
lazy_vacuum_heap(onerel, vacrelstats);
|
||||
/* Forget the now-vacuumed tuples, and press on */
|
||||
@ -378,6 +382,9 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
|
||||
ReleaseBuffer(buf);
|
||||
}
|
||||
|
||||
/* save stats for use later */
|
||||
vacrelstats->rel_tuples = num_tuples;
|
||||
|
||||
/* If any tuples need to be deleted, perform final vacuum cycle */
|
||||
/* XXX put a threshold on min nuber of tuples here? */
|
||||
if (vacrelstats->num_dead_tuples > 0)
|
||||
@ -388,9 +395,12 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
|
||||
/* Remove tuples from heap */
|
||||
lazy_vacuum_heap(onerel, vacrelstats);
|
||||
}
|
||||
|
||||
/* save stats for use later */
|
||||
vacrelstats->rel_tuples = num_tuples;
|
||||
else if (! did_vacuum_index)
|
||||
{
|
||||
/* Scan indexes just to update pg_class statistics about them */
|
||||
for (i = 0; i < nindexes; i++)
|
||||
lazy_scan_index(Irel[i], vacrelstats);
|
||||
}
|
||||
|
||||
elog(MESSAGE_LEVEL, "Pages %u: Changed %u, Empty %u; \
|
||||
Tup %.0f: Vac %.0f, Keep %.0f, UnUsed %.0f.\n\tTotal %s",
|
||||
@ -495,6 +505,68 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
|
||||
return tupindex;
|
||||
}
|
||||
|
||||
/*
|
||||
* lazy_scan_index() -- scan one index relation to update pg_class statistic.
|
||||
*
|
||||
* We use this when we have no deletions to do.
|
||||
*/
|
||||
static void
|
||||
lazy_scan_index(Relation indrel, LVRelStats *vacrelstats)
|
||||
{
|
||||
IndexBulkDeleteResult *stats;
|
||||
VacRUsage ru0;
|
||||
|
||||
vac_init_rusage(&ru0);
|
||||
|
||||
/*
|
||||
* If the index is not partial, skip the scan, and just assume it
|
||||
* has the same number of tuples as the heap.
|
||||
*/
|
||||
if (! vac_is_partial_index(indrel))
|
||||
{
|
||||
vac_update_relstats(RelationGetRelid(indrel),
|
||||
RelationGetNumberOfBlocks(indrel),
|
||||
vacrelstats->rel_tuples,
|
||||
false);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If index is unsafe for concurrent access, must lock it;
|
||||
* but a shared lock should be sufficient.
|
||||
*/
|
||||
if (! indrel->rd_am->amconcurrent)
|
||||
LockRelation(indrel, AccessShareLock);
|
||||
|
||||
/*
|
||||
* Even though we're not planning to delete anything, use the
|
||||
* ambulkdelete call, so that the scan happens within the index AM
|
||||
* for more speed.
|
||||
*/
|
||||
stats = index_bulk_delete(indrel, dummy_tid_reaped, NULL);
|
||||
|
||||
/*
|
||||
* Release lock acquired above.
|
||||
*/
|
||||
if (! indrel->rd_am->amconcurrent)
|
||||
UnlockRelation(indrel, AccessShareLock);
|
||||
|
||||
if (!stats)
|
||||
return;
|
||||
|
||||
/* now update statistics in pg_class */
|
||||
vac_update_relstats(RelationGetRelid(indrel),
|
||||
stats->num_pages, stats->num_index_tuples,
|
||||
false);
|
||||
|
||||
elog(MESSAGE_LEVEL, "Index %s: Pages %u; Tuples %.0f.\n\t%s",
|
||||
RelationGetRelationName(indrel),
|
||||
stats->num_pages, stats->num_index_tuples,
|
||||
vac_show_rusage(&ru0));
|
||||
|
||||
pfree(stats);
|
||||
}
|
||||
|
||||
/*
|
||||
* lazy_vacuum_index() -- vacuum one index relation.
|
||||
*
|
||||
@ -955,6 +1027,15 @@ lazy_tid_reaped(ItemPointer itemptr, void *state)
|
||||
return (res != NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dummy version for lazy_scan_index.
|
||||
*/
|
||||
static bool
|
||||
dummy_tid_reaped(ItemPointer itemptr, void *state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the shared Free Space Map with the info we now have about
|
||||
* free space in the relation, discarding any old info the map may have.
|
||||
|
Reference in New Issue
Block a user