]> granicus.if.org Git - postgresql/commitdiff
New-style vacuum neglected to update pg_class statistics about indexes
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 18 Jul 2001 00:46:25 +0000 (00:46 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 18 Jul 2001 00:46:25 +0000 (00:46 +0000)
if there were no deletions to do.

src/backend/commands/vacuum.c
src/backend/commands/vacuumlazy.c
src/include/commands/vacuum.h

index c53fa05812e1aba3698df949e25b5d5953ab0689..8e141133a427809c043629c54c0d0b5efde32345 100644 (file)
@@ -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),
@@ -2331,6 +2332,15 @@ tid_reaped(ItemPointer itemptr, void *state)
        return true;
 }
 
+/*
+ * 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);
 
index b78f933f0c3c4ecfd1c2d74b2265ee407c4ad9a3..f509086b52f3c5aea094b4f7c1eadd2847e687d5 100644 (file)
@@ -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.
index 9fd6513e91e6b4a7197a1d40d121119b600c9023..0d362bb1801ef58a960f5968b44c9f71bc304877 100644 (file)
@@ -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);