Allow VACUUM to complete faster by avoiding scanning the indexes when no
authorBruce Momjian
Sat, 11 Feb 2006 16:59:09 +0000 (16:59 +0000)
committerBruce Momjian
Sat, 11 Feb 2006 16:59:09 +0000 (16:59 +0000)
rows were removed from the heap by the VACUUM.

Simon Riggs

src/backend/access/gist/gistvacuum.c
src/backend/access/hash/hash.c
src/backend/access/index/indexam.c
src/backend/access/nbtree/nbtree.c
src/backend/commands/vacuum.c
src/backend/commands/vacuumlazy.c
src/include/access/genam.h

index 31c560a83ad4d6a91e550b86fb8805f534fe7ee2..10bd6cb4dc16443eab32bb12fd0ac64337383f3f 100644 (file)
@@ -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.11 2005/11/22 18:17:05 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.12 2006/02/11 16:59:08 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -125,7 +125,7 @@ gistVacuumUpdate(GistVacuum *gv, BlockNumber blkno, bool needunion)
                    if (chldtuple.ituplen > 1)
                    {
                        /*
-                        * child was splitted, so we need mark completion
+                        * child was split, so we need mark completion
                         * insert(split)
                         */
                        int         j;
@@ -329,9 +329,9 @@ gistVacuumUpdate(GistVacuum *gv, BlockNumber blkno, bool needunion)
 }
 
 /*
- * For usial vacuum just update FSM, for full vacuum
+ * For usual vacuum just update FSM, for full vacuum
  * reforms parent tuples if some of childs was deleted or changed,
- * update invalid tuples (they can exsist from last crash recovery only),
+ * update invalid tuples (they can exist from last crash recovery only),
  * tries to get smaller index
  */
 
@@ -505,10 +505,15 @@ gistbulkdelete(PG_FUNCTION_ARGS)
               *ptr;
    bool        needLock;
 
-   stack = (GistBDItem *) palloc0(sizeof(GistBDItem));
+    if (callback_state)
+    {
+       stack = (GistBDItem *) palloc0(sizeof(GistBDItem));
 
-   stack->blkno = GIST_ROOT_BLKNO;
-   needFullVacuum = false;
+      stack->blkno = GIST_ROOT_BLKNO;
+      needFullVacuum = false;
+    }
+    else
+        stack = NULL;
 
    while (stack)
    {
index 3a01109125f4381033d7a6ef709d8a53571dd514..548901a9be465057e5a04a2308ecea13adc5b583 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.83 2006/01/25 23:26:11 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.84 2006/02/11 16:59:09 momjian Exp $
  *
  * NOTES
  *   This file contains only the public interface routines.
@@ -496,6 +496,17 @@ hashbulkdelete(PG_FUNCTION_ARGS)
    tuples_removed = 0;
    num_index_tuples = 0;
 
+   /* return statistics */
+   num_pages = RelationGetNumberOfBlocks(rel);
+
+   result = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+   result->num_pages = num_pages;
+
+    if (!callback_state)
+    {
+           PG_RETURN_POINTER(result);
+    }
+
    /*
     * Read the metapage to fetch original bucket and tuple counts.  Also, we
     * keep a copy of the last-seen metapage so that we can use its
@@ -644,11 +655,6 @@ loop_top:
 
    _hash_wrtbuf(rel, metabuf);
 
-   /* return statistics */
-   num_pages = RelationGetNumberOfBlocks(rel);
-
-   result = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
-   result->num_pages = num_pages;
    result->num_index_tuples = num_index_tuples;
    result->tuples_removed = tuples_removed;
 
index c1e61ff2bda32f883247c4e3a1f18ec6033cb23e..0365ae7942403923ccdc7860f268257633df470f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.87 2005/12/03 05:51:00 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.88 2006/02/11 16:59:09 momjian Exp $
  *
  * INTERFACE ROUTINES
  *     index_open      - open an index relation by relation OID
@@ -685,6 +685,11 @@ index_getmulti(IndexScanDesc scan,
  *     callback routine tells whether a given main-heap tuple is
  *     to be deleted
  *
+ *      passing NULL callback_state can be interpreted by the 
+ *      index access method as meaning that the index does not need
+ *      to be scanned in logical sequence to remove rows for this call
+ *      index_vacuum_cleanup is always required after this, however.
+ * 
  *     return value is an optional palloc'd struct of statistics
  * ----------------
  */
index 45f49c0b2bd78582267549f6301f4735d699a594..e757c4adad10f20c8d89cfd21db5cee89cadf169 100644 (file)
@@ -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.136 2006/01/25 23:04:20 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.137 2006/02/11 16:59:09 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -543,8 +543,9 @@ btbulkdelete(PG_FUNCTION_ARGS)
    double      num_index_tuples;
    OffsetNumber deletable[MaxOffsetNumber];
    int         ndeletable;
-   Buffer      buf;
+   Buffer      buf = NULL;
    BlockNumber num_pages;
+    bool        scanindex = true;
 
    tuples_removed = 0;
    num_index_tuples = 0;
@@ -565,8 +566,15 @@ btbulkdelete(PG_FUNCTION_ARGS)
     * skip obtaining exclusive lock on empty pages though, since no indexscan
     * could be stopped on those.
     */
-   buf = _bt_get_endpoint(rel, 0, false);
-   if (BufferIsValid(buf))     /* check for empty index */
+    if (callback_state)
+    {
+       buf = _bt_get_endpoint(rel, 0, false);
+        scanindex = BufferIsValid(buf); /* check for empty index */
+    }
+    else
+        scanindex = false;
+
+   if (scanindex)  
    {
        for (;;)
        {
@@ -649,7 +657,10 @@ btbulkdelete(PG_FUNCTION_ARGS)
 
    result = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
    result->num_pages = num_pages;
-   result->num_index_tuples = num_index_tuples;
+    if (scanindex)
+       result->num_index_tuples = num_index_tuples;
+    else
+        result->num_index_tuples = -1;
    result->tuples_removed = tuples_removed;
 
    PG_RETURN_POINTER(result);
index 4a66f10bd72a813273f9e08b3ffd04fbb814f084..4e7775a6cda052764e68f46c35f914f8dfdde276 100644 (file)
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.321 2006/01/18 20:35:05 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.322 2006/02/11 16:59:09 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -719,7 +719,8 @@ vac_update_relstats(Oid relid, BlockNumber num_pages, double num_tuples,
    /* overwrite the existing statistics in the tuple */
    pgcform = (Form_pg_class) GETSTRUCT(&rtup);
    pgcform->relpages = (int32) num_pages;
-   pgcform->reltuples = (float4) num_tuples;
+    if (num_tuples >= 0 )
+       pgcform->reltuples = (float4) num_tuples;
    pgcform->relhasindex = hasindex;
 
    /*
@@ -2961,15 +2962,18 @@ scan_index(Relation indrel, double num_tuples)
    if (!stats)
        return;
 
-   /* now update statistics in pg_class */
+   /* now update statistics in pg_class 
+     * we use the number of tuples from the table because we have not
+     * actually scanned the index, so don't know the number of tuples in index
+     */
    vac_update_relstats(RelationGetRelid(indrel),
-                       stats->num_pages, stats->num_index_tuples,
+                       stats->num_pages, num_tuples,
                        false);
 
    ereport(elevel,
            (errmsg("index \"%s\" now contains %.0f row versions in %u pages",
                    RelationGetRelationName(indrel),
-                   stats->num_index_tuples,
+                   num_tuples,
                    stats->num_pages),
    errdetail("%u index pages have been deleted, %u are currently reusable.\n"
              "%s.",
index fbdb019b351ba7d08f5abe3657a3a47ba41080b6..0b2789da48515fdb72ed1032dfe009cb3704a520 100644 (file)
@@ -31,7 +31,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.63 2005/11/22 18:17:09 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.64 2006/02/11 16:59:09 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -639,16 +639,19 @@ lazy_scan_index(Relation indrel, LVRelStats *vacrelstats)
    if (!stats)
        return;
 
-   /* now update statistics in pg_class */
+   /* now update statistics in pg_class
+     * we use the number of tuples from the table because we have not
+     * actually scanned the index, so don't know the number of tuples in index
+     */
    vac_update_relstats(RelationGetRelid(indrel),
                        stats->num_pages,
-                       stats->num_index_tuples,
+                       vacrelstats->rel_tuples, 
                        false);
 
    ereport(elevel,
            (errmsg("index \"%s\" now contains %.0f row versions in %u pages",
                    RelationGetRelationName(indrel),
-                   stats->num_index_tuples,
+                   vacrelstats->rel_tuples,
                    stats->num_pages),
    errdetail("%u index pages have been deleted, %u are currently reusable.\n"
              "%s.",
index 7dc33d3138cc766f86fb56f7e0e802df1f4b3f4a..ef9ca2146b9734b84b5cbf123fc83d32234d5d25 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/genam.h,v 1.54 2005/12/03 05:51:03 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/genam.h,v 1.55 2006/02/11 16:59:09 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -38,6 +38,8 @@ typedef struct IndexBulkDeleteResult
    BlockNumber num_pages;      /* pages remaining in index */
    BlockNumber pages_removed;  /* # removed by bulk-delete operation */
    double      num_index_tuples;       /* tuples remaining */
+                                /* should set to -1 if index not scanned */
+                                /*   because no records to delete        */
    double      tuples_removed; /* # removed by bulk-delete operation */
    BlockNumber pages_deleted;  /* # unused pages in index */
    BlockNumber pages_free;     /* # pages available for reuse */