aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2001-07-18 00:46:25 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2001-07-18 00:46:25 +0000
commitccf193f1a595106cacb946a41ef39e1cb2259e60 (patch)
tree82117d9c333a723f6c786282a69c9b0b637347aa
parent75586cb584300393d7cde0dde292fb82ec18b3d5 (diff)
downloadpostgresql-ccf193f1a595106cacb946a41ef39e1cb2259e60.tar.gz
postgresql-ccf193f1a595106cacb946a41ef39e1cb2259e60.zip
New-style vacuum neglected to update pg_class statistics about indexes
if there were no deletions to do.
-rw-r--r--src/backend/commands/vacuum.c69
-rw-r--r--src/backend/commands/vacuumlazy.c89
-rw-r--r--src/include/commands/vacuum.h3
3 files changed, 128 insertions, 33 deletions
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index c53fa05812e..8e141133a42 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -13,7 +13,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.205 2001/07/15 22:48:17 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.206 2001/07/18 00:46:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -129,11 +129,11 @@ static void vacuum_index(VacPageList vacpagelist, Relation indrel,
double num_tuples, int keep_tuples);
static void scan_index(Relation indrel, double num_tuples);
static bool tid_reaped(ItemPointer itemptr, void *state);
+static bool dummy_tid_reaped(ItemPointer itemptr, void *state);
static void vac_update_fsm(Relation onerel, VacPageList fraged_pages,
BlockNumber rel_pages);
static VacPage copy_vac_page(VacPage vacpage);
static void vpage_insert(VacPageList vacpagelist, VacPage vpnew);
-static bool is_partial_index(Relation indrel);
static void *vac_bsearch(const void *key, const void *base,
size_t nelem, size_t size,
int (*compar) (const void *, const void *));
@@ -2178,51 +2178,52 @@ vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage)
/*
* scan_index() -- scan one index relation to update statistic.
+ *
+ * We use this when we have no deletions to do.
*/
static void
scan_index(Relation indrel, double num_tuples)
{
- RetrieveIndexResult res;
- IndexScanDesc iscan;
- BlockNumber nipages;
- double nitups;
+ IndexBulkDeleteResult *stats;
VacRUsage ru0;
vac_init_rusage(&ru0);
- /* walk through the entire index */
- iscan = index_beginscan(indrel, false, 0, (ScanKey) NULL);
- nitups = 0;
-
- while ((res = index_getnext(iscan, ForwardScanDirection))
- != (RetrieveIndexResult) NULL)
- {
- nitups += 1;
- pfree(res);
- }
+ /*
+ * 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);
- index_endscan(iscan);
+ if (!stats)
+ return;
/* now update statistics in pg_class */
- nipages = RelationGetNumberOfBlocks(indrel);
- vac_update_relstats(RelationGetRelid(indrel), nipages, nitups, false);
+ 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), nipages, nitups,
+ RelationGetRelationName(indrel),
+ stats->num_pages, stats->num_index_tuples,
vac_show_rusage(&ru0));
/*
* Check for tuple count mismatch. If the index is partial, then
* it's OK for it to have fewer tuples than the heap; else we got trouble.
*/
- if (nitups != num_tuples)
+ if (stats->num_index_tuples != num_tuples)
{
- if (nitups > num_tuples ||
- ! is_partial_index(indrel))
+ if (stats->num_index_tuples > num_tuples ||
+ ! vac_is_partial_index(indrel))
elog(NOTICE, "Index %s: NUMBER OF INDEX' TUPLES (%.0f) IS NOT THE SAME AS HEAP' (%.0f).\
\n\tRecreate the index.",
- RelationGetRelationName(indrel), nitups, num_tuples);
+ RelationGetRelationName(indrel),
+ stats->num_index_tuples, num_tuples);
}
+
+ pfree(stats);
}
/*
@@ -2269,7 +2270,7 @@ vacuum_index(VacPageList vacpagelist, Relation indrel,
if (stats->num_index_tuples != num_tuples + keep_tuples)
{
if (stats->num_index_tuples > num_tuples + keep_tuples ||
- ! is_partial_index(indrel))
+ ! vac_is_partial_index(indrel))
elog(NOTICE, "Index %s: NUMBER OF INDEX' TUPLES (%.0f) IS NOT THE SAME AS HEAP' (%.0f).\
\n\tRecreate the index.",
RelationGetRelationName(indrel),
@@ -2332,6 +2333,15 @@ tid_reaped(ItemPointer itemptr, void *state)
}
/*
+ * Dummy version for 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.
*/
@@ -2552,8 +2562,11 @@ vac_close_indexes(int nindexes, Relation *Irel)
}
-static bool
-is_partial_index(Relation indrel)
+/*
+ * Is an index partial (ie, could it contain fewer tuples than the heap?)
+ */
+bool
+vac_is_partial_index(Relation indrel)
{
bool result;
HeapTuple cachetuple;
@@ -2570,7 +2583,7 @@ is_partial_index(Relation indrel)
ObjectIdGetDatum(RelationGetRelid(indrel)),
0, 0, 0);
if (!HeapTupleIsValid(cachetuple))
- elog(ERROR, "is_partial_index: index %u not found",
+ elog(ERROR, "vac_is_partial_index: index %u not found",
RelationGetRelid(indrel));
indexStruct = (Form_pg_index) GETSTRUCT(cachetuple);
diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c
index b78f933f0c3..f509086b52f 100644
--- a/src/backend/commands/vacuumlazy.c
+++ b/src/backend/commands/vacuumlazy.c
@@ -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",
@@ -496,6 +506,68 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
}
/*
+ * 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.
*
* Delete all the index entries pointing to tuples listed in
@@ -956,6 +1028,15 @@ lazy_tid_reaped(ItemPointer itemptr, void *state)
}
/*
+ * 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.
*/
diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h
index 9fd6513e91e..0d362bb1801 100644
--- a/src/include/commands/vacuum.h
+++ b/src/include/commands/vacuum.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: vacuum.h,v 1.38 2001/07/13 22:55:59 tgl Exp $
+ * $Id: vacuum.h,v 1.39 2001/07/18 00:46:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -44,6 +44,7 @@ extern void vac_update_relstats(Oid relid,
BlockNumber num_pages,
double num_tuples,
bool hasindex);
+extern bool vac_is_partial_index(Relation indrel);
extern void vac_init_rusage(VacRUsage *ru0);
extern const char *vac_show_rusage(VacRUsage *ru0);