]> granicus.if.org Git - postgresql/commitdiff
Cost based vacuum delay feature.
authorJan Wieck <JanWieck@Yahoo.com>
Fri, 6 Feb 2004 19:36:18 +0000 (19:36 +0000)
committerJan Wieck <JanWieck@Yahoo.com>
Fri, 6 Feb 2004 19:36:18 +0000 (19:36 +0000)
Jan

src/backend/access/nbtree/nbtree.c
src/backend/commands/vacuumlazy.c
src/backend/storage/buffer/bufmgr.c
src/backend/storage/buffer/freelist.c
src/backend/tcop/postgres.c
src/backend/utils/init/globals.c
src/backend/utils/misc/guc.c
src/backend/utils/misc/postgresql.conf.sample
src/include/miscadmin.h

index b423c8fdbe8ae3f9e4f745e31696a0b9f228f99d..87a251915a5e0ae8a747ee24e70530bfea72dc71 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.110 2004/02/03 17:34:02 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.111 2004/02/06 19:36:17 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -586,6 +586,26 @@ btbulkdelete(PG_FUNCTION_ARGS)
 
                        CHECK_FOR_INTERRUPTS();
 
+                       /*
+                        * If we're called by a cost based vacuum, do the
+                        * napping in case the balance exceeded the limit.
+                        */
+                       if (VacuumCostActive && !InterruptPending &&
+                                       VacuumCostBalance >= VacuumCostLimit)
+                       {
+                               int             msec;
+
+                               msec = VacuumCostNaptime * VacuumCostBalance / VacuumCostLimit;
+                               if (msec < VacuumCostNaptime * 4)
+                                       PG_MSLEEP(msec);
+                               else
+                                       PG_MSLEEP(VacuumCostNaptime * 4);
+
+                               VacuumCostBalance = 0;
+
+                               CHECK_FOR_INTERRUPTS();
+                       }
+
                        ndeletable = 0;
                        page = BufferGetPage(buf);
                        opaque = (BTPageOpaque) PageGetSpecialPointer(page);
index 14c66b498d302c8e98827293791e52ab4e2bf495..c271152877054a24d2c94033ec0d75fc7b559a8f 100644 (file)
@@ -31,7 +31,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.34 2004/02/03 17:34:02 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.35 2004/02/06 19:36:17 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -148,6 +148,11 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt)
        vac_open_indexes(onerel, &nindexes, &Irel);
        hasindex = (nindexes > 0);
 
+       /* Turn on vacuum cost accounting */
+       if (VacuumCostNaptime > 0)
+               VacuumCostActive = true;
+       VacuumCostBalance = 0;
+
        /* Do the vacuuming */
        lazy_scan_heap(onerel, vacrelstats, Irel, nindexes);
 
@@ -168,6 +173,9 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt)
        /* Update shared free space map with final free space info */
        lazy_update_fsm(onerel, vacrelstats);
 
+       /* Turn off vacuum cost accounting */
+       VacuumCostActive = false;
+
        /* Update statistics in pg_class */
        vac_update_relstats(RelationGetRelid(onerel), vacrelstats->rel_pages,
                                                vacrelstats->rel_tuples, hasindex);
@@ -228,6 +236,25 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
 
                CHECK_FOR_INTERRUPTS();
 
+               /*
+                * Do the napping in a cost based vacuum.
+                */
+               if (VacuumCostActive && !InterruptPending &&
+                               VacuumCostBalance >= VacuumCostLimit)
+               {
+                       int             msec;
+
+                       msec = VacuumCostNaptime * VacuumCostBalance / VacuumCostLimit;
+                       if (msec < VacuumCostNaptime * 4)
+                               PG_MSLEEP(msec);
+                       else
+                               PG_MSLEEP(VacuumCostNaptime * 4);
+
+                       VacuumCostBalance = 0;
+
+                       CHECK_FOR_INTERRUPTS();
+               }
+
                /*
                 * If we are close to overrunning the available space for
                 * dead-tuple TIDs, pause and do a cycle of vacuuming before we
@@ -469,6 +496,25 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats)
 
                CHECK_FOR_INTERRUPTS();
 
+               /*
+                * Do the napping in a cost based vacuum.
+                */
+               if (VacuumCostActive && !InterruptPending &&
+                               VacuumCostBalance >= VacuumCostLimit)
+               {
+                       int             msec;
+
+                       msec = VacuumCostNaptime * VacuumCostBalance / VacuumCostLimit;
+                       if (msec < VacuumCostNaptime * 4)
+                               PG_MSLEEP(msec);
+                       else
+                               PG_MSLEEP(VacuumCostNaptime * 4);
+
+                       VacuumCostBalance = 0;
+
+                       CHECK_FOR_INTERRUPTS();
+               }
+
                tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples[tupindex]);
                buf = ReadBuffer(onerel, tblk);
                LockBufferForCleanup(buf);
@@ -800,6 +846,25 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
 
                CHECK_FOR_INTERRUPTS();
 
+               /*
+                * Do the napping in a cost based vacuum.
+                */
+               if (VacuumCostActive && !InterruptPending &&
+                               VacuumCostBalance >= VacuumCostLimit)
+               {
+                       int             msec;
+
+                       msec = VacuumCostNaptime * VacuumCostBalance / VacuumCostLimit;
+                       if (msec < VacuumCostNaptime * 4)
+                               PG_MSLEEP(msec);
+                       else
+                               PG_MSLEEP(VacuumCostNaptime * 4);
+
+                       VacuumCostBalance = 0;
+
+                       CHECK_FOR_INTERRUPTS();
+               }
+
                blkno--;
 
                buf = ReadBuffer(onerel, blkno);
index cb82159aff02f528cf512774677e29bdecef982b..b927b5ea5e7ed164e7b626d965e0095be56248a3 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.155 2004/02/04 01:24:53 wieck Exp $
+ *       $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.156 2004/02/06 19:36:18 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -576,6 +576,12 @@ write_buffer(Buffer buffer, bool release)
        LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
        Assert(bufHdr->refcount > 0);
 
+       /*
+        * If the buffer is not dirty yet, do vacuum cost accounting.
+        */
+       if (!(bufHdr->flags & BM_DIRTY) && VacuumCostActive)
+               VacuumCostBalance += VacuumCostPageDirty;
+
        bufHdr->flags |= (BM_DIRTY | BM_JUST_DIRTIED);
 
        if (release)
index 6388bc724d973f287347c690d6edb4caabc9fd17..74ec4518ab90fdec2b61310df342a862f930987a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/storage/buffer/freelist.c,v 1.39 2004/01/15 16:14:26 wieck Exp $
+ *       $PostgreSQL: pgsql/src/backend/storage/buffer/freelist.c,v 1.40 2004/02/06 19:36:18 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -31,6 +31,7 @@
 #include "storage/ipc.h"
 #include "storage/proc.h"
 #include "access/xact.h"
+#include "miscadmin.h"
 
 #ifndef MAX
 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
@@ -237,6 +238,12 @@ StrategyBufferLookup(BufferTag *tagPtr, bool recheck)
                                strategy_get_from = STRAT_LIST_T2;
                }
 
+               /*
+                * Do the cost accounting for vacuum
+                */
+               if (VacuumCostActive)
+                       VacuumCostBalance += VacuumCostPageMiss;
+
                /* report cache miss */
                return NULL;
        }
@@ -250,6 +257,8 @@ StrategyBufferLookup(BufferTag *tagPtr, bool recheck)
         * Count hits
         */
        StrategyControl->num_hit[cdb->list]++;
+       if (VacuumCostActive)
+               VacuumCostBalance += VacuumCostPageHit;
 
        /*
         * If this is a T2 hit, we simply move the CDB to the
index 1ea95d2e5071cc702aa5fd2a18bd4de620a2ab63..735e5aa69d3e1eb6f2ddb55dc0f13622790baaae 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.388 2004/02/03 17:34:03 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.389 2004/02/06 19:36:18 wieck Exp $
  *
  * NOTES
  *       this is the "main" module of the postgres backend and
@@ -2707,6 +2707,11 @@ PostgresMain(int argc, char *argv[], const char *username)
                InError = false;
                xact_started = false;
 
+               /*
+                * Clear flag that causes accounting for cost based vacuum.
+                */
+               VacuumCostActive = false;
+
                /*
                 * If we were handling an extended-query-protocol message,
                 * initiate skip till next Sync.  This also causes us not to issue
index c170ae603df3baf2c4dfa9ca30e3f8f5190d16a5..f916d013d1c129a0812bf0924395bcef96fd1a88 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/init/globals.c,v 1.82 2004/02/03 17:34:03 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/init/globals.c,v 1.83 2004/02/06 19:36:18 wieck Exp $
  *
  * NOTES
  *       Globals used all over the place should be declared here and not
@@ -81,3 +81,11 @@ bool         allowSystemTableMods = false;
 int                    work_mem = 1024;
 int                    maintenance_work_mem = 16384;
 int                    NBuffers = 1000;
+
+int                    VacuumCostPageHit = 1;
+int                    VacuumCostPageMiss = 10;
+int                    VacuumCostPageDirty = 20;
+int                    VacuumCostLimit = 200;
+int                    VacuumCostBalance = 0;
+int                    VacuumCostNaptime = 0;
+bool           VacuumCostActive = false;
index eb79ea2c627dab4d1b66779d1e5e5a2bd926ff84..7fe7c33cf8a5be23b68ec3ce5865a728eeb43fde 100644 (file)
@@ -10,7 +10,7 @@
  * Written by Peter Eisentraut <peter_e@gmx.net>.
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.185 2004/02/04 01:24:53 wieck Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.186 2004/02/06 19:36:18 wieck Exp $
  *
  *--------------------------------------------------------------------
  */
@@ -1047,6 +1047,51 @@ static struct config_int ConfigureNamesInt[] =
                16384, 1024, INT_MAX / 1024, NULL, NULL
        },
 
+       {
+               {"vacuum_cost_page_hit", PGC_USERSET, RESOURCES,
+                       gettext_noop("Vacuum cost for a page found in the buffer cache."),
+                       NULL
+               },
+               &VacuumCostPageHit,
+               1, 0, 10000, NULL, NULL
+       },
+
+       {
+               {"vacuum_cost_page_miss", PGC_USERSET, RESOURCES,
+                       gettext_noop("Vacuum cost for a page not found in the buffer cache."),
+                       NULL
+               },
+               &VacuumCostPageMiss,
+               10, 0, 10000, NULL, NULL
+       },
+
+       {
+               {"vacuum_cost_page_dirty", PGC_USERSET, RESOURCES,
+                       gettext_noop("Vacuum cost for a page dirtied by vacuum."),
+                       NULL
+               },
+               &VacuumCostPageDirty,
+               20, 0, 10000, NULL, NULL
+       },
+
+       {
+               {"vacuum_cost_limit", PGC_USERSET, RESOURCES,
+                       gettext_noop("Vacuum cost amount available before napping."),
+                       NULL
+               },
+               &VacuumCostLimit,
+               200, 1, 10000, NULL, NULL
+       },
+
+       {
+               {"vacuum_cost_naptime", PGC_USERSET, RESOURCES,
+                       gettext_noop("Vacuum cost naptime in milliseconds."),
+                       NULL
+               },
+               &VacuumCostNaptime,
+               0, 0, 1000, NULL, NULL
+       },
+
        {
                {"max_files_per_process", PGC_BACKEND, RESOURCES_KERNEL,
                        gettext_noop("Sets the maximum number of simultaneously open files for each server process."),
index ad6f6bfcfeff803071aa05db15f688dc3bb3c1dc..ee7b47c04dc1402e06a58bad7fe62c4197ec7d58 100644 (file)
 #maintenance_work_mem = 16384  # min 1024, size in KB
 #debug_shared_buffers = 0      # 0-600 seconds
 
+#vacuum_cost_page_hit = 1      # 0-10000 credits
+#vacuum_cost_page_miss = 10    # 0-10000 credits
+#vacuum_cost_page_dirty = 20   # 0-10000 credits
+#vacuum_cost_limit = 200               # 0-10000 credits
+#vacuum_cost_naptime = 50      # 0-1000 milliseconds
+
 # - Background writer -
 #bgwriter_delay = 200          # 10-5000 milliseconds
 #bgwriter_percent = 1          # 0-100% of dirty buffers
index a7fe724533e7f34ab337229540382c7a135e0e88..1f71a434c17a458f3fdc0b3b52f8c248740cf327 100644 (file)
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.150 2004/02/03 17:34:03 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.151 2004/02/06 19:36:18 wieck Exp $
  *
  * NOTES
  *       some of the information in this file should be moved to
@@ -106,11 +106,19 @@ do { \
        delay.tv_usec = ((_usec) % 1000000); \
        (void) select(0, NULL, NULL, NULL, &delay); \
 } while(0)
+#define PG_MSLEEP(_msec) \
+do { \
+       struct timeval _delay; \
+       _delay.tv_sec = (_msec) / 1000; \
+       _delay.tv_usec = ((_msec) % 1000) * 1000; \
+       (void) select (0, NULL, NULL, NULL, &_delay); \
+} while(0)
 #else
 #define PG_USLEEP(_usec) \
 do { \
        SleepEx(((_usec) < 500 ? 1 : ((_usec) + 500) / 1000), TRUE); \
 } while(0)
+#define PG_MSLEEP(_msec) PG_USLEEP((_msec) * 1000)
 #endif
 
 #ifdef WIN32
@@ -209,6 +217,15 @@ extern bool enableFsync;
 extern bool allowSystemTableMods;
 extern DLLIMPORT int work_mem;
 extern DLLIMPORT int maintenance_work_mem;
+extern int     VacuumMem;
+
+extern int     VacuumCostPageHit;
+extern int     VacuumCostPageMiss;
+extern int     VacuumCostPageDirty;
+extern int     VacuumCostLimit;
+extern int     VacuumCostBalance;
+extern int     VacuumCostNaptime;
+extern bool    VacuumCostActive;
 
 /*
  *     A few postmaster startup options are exported here so the