Add options to pg_autovacuum to support setting the cost-based-vacuum
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 17 Nov 2004 16:54:15 +0000 (16:54 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 17 Nov 2004 16:54:15 +0000 (16:54 +0000)
parameters differently from their default values.  Matthew T. O'Connor

contrib/pg_autovacuum/README.pg_autovacuum
contrib/pg_autovacuum/pg_autovacuum.c
contrib/pg_autovacuum/pg_autovacuum.h

index 3cb633000e63171be9e3b57881f2b66553fc4f38..693848ceaa23f30280c610fea1c2c26064ef5109 100644 (file)
@@ -133,6 +133,17 @@ pg_autovacuum has the following optional arguments:
 -p port: port used for connection.
 -h help: list of command line options.
 
+The following 5 autovacuum command line options correspond to the various
+cost-based vacuum settings.  If not given, then the cluster default values
+will be used.
+
+-c     vacuum_cost_delay
+-C     vacuum_cost_page_hit
+-m     vacuum_cost_page_miss
+-n     vacuum_cost_page_dirty
+-N     vacuum_cost_limit
+
+
 Numerous arguments have default values defined in pg_autovacuum.h.  At
 the time of writing they are:
 
index 4ed30604f9f4c9ee066bf6eec55f44a110ff86ea..953404555ad4a767c5c7fd900f1ddcbe490439cf 100644 (file)
@@ -4,7 +4,7 @@
  * Revisions by Christopher B. Browne, Liberty RMS
  * Win32 Service code added by Dave Page
  *
- * $PostgreSQL: pgsql/contrib/pg_autovacuum/pg_autovacuum.c,v 1.23 2004/10/25 02:14:59 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/pg_autovacuum/pg_autovacuum.c,v 1.24 2004/11/17 16:54:15 tgl Exp $
  */
 
 #include "postgres_fe.h"
@@ -530,7 +530,7 @@ print_table_info(tbl_info * tbl)
 {
        sprintf(logbuffer, "  table name: %s.%s", tbl->dbi->dbname, tbl->table_name);
        log_entry(logbuffer, LVL_INFO);
-       sprintf(logbuffer, "     relid: %u;   relisshared: %i", tbl->relid, tbl->relisshared);
+       sprintf(logbuffer, "     relid: %u;   relisshared: %d", tbl->relid, tbl->relisshared);
        log_entry(logbuffer, LVL_INFO);
        sprintf(logbuffer, "     reltuples: %f;  relpages: %u", tbl->reltuples, tbl->relpages);
        log_entry(logbuffer, LVL_INFO);
@@ -905,6 +905,7 @@ db_connect(db_info * dbi)
                PQfinish(db_conn);
                db_conn = NULL;
        }
+               
        return db_conn;
 }      /* end of db_connect() */
 
@@ -973,6 +974,75 @@ send_query(const char *query, db_info * dbi)
        return res;
 }      /* End of send_query() */
 
+/*
+ * Perform either a vacuum or a vacuum analyze
+ */
+static void
+perform_maintenance_command(db_info * dbi, tbl_info * tbl, int operation)
+{
+       char            buf[256];
+       
+       /* 
+        * Set the vacuum_cost variables if supplied on command line
+        */     
+       if (args->av_vacuum_cost_delay != -1)
+       {       
+               snprintf(buf, sizeof(buf), "set vacuum_cost_delay = %d",
+                                args->av_vacuum_cost_delay);
+               send_query(buf, dbi);
+       }
+       if (args->av_vacuum_cost_page_hit != -1)
+       {       
+               snprintf(buf, sizeof(buf), "set vacuum_cost_page_hit = %d",
+                                args->av_vacuum_cost_page_hit);
+               send_query(buf, dbi);
+       }
+       if (args->av_vacuum_cost_page_miss != -1)
+       {       
+               snprintf(buf, sizeof(buf), "set vacuum_cost_page_miss = %d",
+                                args->av_vacuum_cost_page_miss);
+               send_query(buf, dbi);
+       }
+       if (args->av_vacuum_cost_page_dirty != -1)
+       {       
+               snprintf(buf, sizeof(buf), "set vacuum_cost_page_dirty = %d",
+                                args->av_vacuum_cost_page_dirty);
+               send_query(buf, dbi);
+       }
+       if (args->av_vacuum_cost_limit != -1)
+       {       
+               snprintf(buf, sizeof(buf), "set vacuum_cost_limit = %d",
+                                args->av_vacuum_cost_limit);
+               send_query(buf, dbi);
+       }
+       
+       /*
+        * if ((relisshared = t and database != template1) or 
+        * if operation = ANALYZE_ONLY) 
+        * then only do an analyze
+        */
+       if ((tbl->relisshared > 0 && strcmp("template1", dbi->dbname) != 0) ||
+               (operation == ANALYZE_ONLY))
+               snprintf(buf, sizeof(buf), "ANALYZE %s", tbl->table_name);
+       else if (operation == VACUUM_ANALYZE)
+               snprintf(buf, sizeof(buf), "VACUUM ANALYZE %s", tbl->table_name);
+       else
+               return;
+                       
+       if (args->debug >= 1)
+       {
+               sprintf(logbuffer, "Performing: %s", buf);
+               log_entry(logbuffer, LVL_DEBUG);
+               fflush(LOGOUTPUT);
+       }
+       
+       send_query(buf, dbi);
+
+       update_table_thresholds(dbi, tbl, operation);
+
+       if (args->debug >= 2)
+               print_table_info(tbl);
+}
 
 static void
 free_cmd_args(void)
@@ -1014,14 +1084,23 @@ get_cmd_args(int argc, char *argv[])
        args->logfile = 0;
        args->port = 0;
 
+       /*
+        * Cost-Based Vacuum Delay Settings for pg_autovacuum 
+        */
+       args->av_vacuum_cost_delay = -1;
+       args->av_vacuum_cost_page_hit = -1;
+       args->av_vacuum_cost_page_miss = -1;
+       args->av_vacuum_cost_page_dirty = -1;
+       args->av_vacuum_cost_limit = -1;
+
        /*
         * Fixme: Should add some sanity checking such as positive integer
         * values etc
         */
 #ifndef WIN32
-       while ((c = getopt(argc, argv, "s:S:v:V:a:A:d:U:P:H:L:p:hD")) != -1)
+       while ((c = getopt(argc, argv, "s:S:v:V:a:A:d:U:P:H:L:p:hD:c:C:m:n:N:")) != -1)
 #else
-       while ((c = getopt(argc, argv, "s:S:v:V:a:A:d:U:P:H:L:p:hIRN:W:")) != -1)
+       while ((c = getopt(argc, argv, "s:S:v:V:a:A:d:U:P:H:L:p:hIRN:W:c:C:m:n:N:")) != -1)
 #endif
        {
                switch (c)
@@ -1044,6 +1123,21 @@ get_cmd_args(int argc, char *argv[])
                        case 'A':
                                args->analyze_scaling_factor = atof(optarg);
                                break;
+                       case 'c':
+                               args->av_vacuum_cost_delay = atoi(optarg);
+                               break;
+                       case 'C':
+                               args->av_vacuum_cost_page_hit = atoi(optarg);
+                               break;
+                       case 'm':
+                               args->av_vacuum_cost_page_miss = atoi(optarg);
+                               break;
+                       case 'n':
+                               args->av_vacuum_cost_page_dirty = atoi(optarg);
+                               break;
+                       case 'N':
+                               args->av_vacuum_cost_limit = atoi(optarg);
+                               break;
 #ifndef WIN32
                        case 'D':
                                args->daemonize++;
@@ -1124,24 +1218,30 @@ usage(void)
        fprintf(stderr, "   [-W] Password to run service with (only useful when installing as a Windows service)\n");
 #endif
        i = AUTOVACUUM_DEBUG;
-       fprintf(stderr, "   [-d] debug (debug level=0,1,2,3; default=%i)\n", i);
+       fprintf(stderr, "   [-d] debug (debug level=0,1,2,3; default=%d)\n", i);
 
        i = SLEEPBASEVALUE;
-       fprintf(stderr, "   [-s] sleep base value (default=%i)\n", i);
+       fprintf(stderr, "   [-s] sleep base value (default=%d)\n", i);
        f = SLEEPSCALINGFACTOR;
        fprintf(stderr, "   [-S] sleep scaling factor (default=%f)\n", f);
 
        i = VACBASETHRESHOLD;
-       fprintf(stderr, "   [-v] vacuum base threshold (default=%i)\n", i);
+       fprintf(stderr, "   [-v] vacuum base threshold (default=%d)\n", i);
        f = VACSCALINGFACTOR;
        fprintf(stderr, "   [-V] vacuum scaling factor (default=%f)\n", f);
        i = i / 2;
-       fprintf(stderr, "   [-a] analyze base threshold (default=%i)\n", i);
+       fprintf(stderr, "   [-a] analyze base threshold (default=%d)\n", i);
        f = f / 2;
        fprintf(stderr, "   [-A] analyze scaling factor (default=%f)\n", f);
 
        fprintf(stderr, "   [-L] logfile (default=none)\n");
 
+       fprintf(stderr, "   [-c] vacuum_cost_delay (default=none)\n");
+       fprintf(stderr, "   [-C] vacuum_cost_page_hit (default=none)\n");
+       fprintf(stderr, "   [-m] vacuum_cost_page_miss (default=none)\n");
+       fprintf(stderr, "   [-n] vacuum_cost_page_dirty (default=none)\n");
+       fprintf(stderr, "   [-N] vacuum_cost_limit (default=none)\n");
+       
        fprintf(stderr, "   [-U] username (libpq default)\n");
        fprintf(stderr, "   [-P] password (libpq default)\n");
        fprintf(stderr, "   [-H] host (libpq default)\n");
@@ -1166,12 +1266,12 @@ print_cmd_args(void)
        sprintf(logbuffer, "  args->logfile=%s", (args->logfile) ? args->logfile : "(null)");
        log_entry(logbuffer, LVL_INFO);
 #ifndef WIN32
-       sprintf(logbuffer, "  args->daemonize=%i", args->daemonize);
+       sprintf(logbuffer, "  args->daemonize=%d", args->daemonize);
        log_entry(logbuffer, LVL_INFO);
 #else
-       sprintf(logbuffer, "  args->install_as_service=%i", args->install_as_service);
+       sprintf(logbuffer, "  args->install_as_service=%d", args->install_as_service);
        log_entry(logbuffer, LVL_INFO);
-       sprintf(logbuffer, "  args->remove_as_service=%i", args->remove_as_service);
+       sprintf(logbuffer, "  args->remove_as_service=%d", args->remove_as_service);
        log_entry(logbuffer, LVL_INFO);
        sprintf(logbuffer, "  args->service_user=%s", (args->service_user) ? args->service_user : "(null)");
        log_entry(logbuffer, LVL_INFO);
@@ -1179,19 +1279,46 @@ print_cmd_args(void)
        log_entry(logbuffer, LVL_INFO);
 #endif
 
-       sprintf(logbuffer, "  args->sleep_base_value=%i", args->sleep_base_value);
+       sprintf(logbuffer, "  args->sleep_base_value=%d", args->sleep_base_value);
        log_entry(logbuffer, LVL_INFO);
        sprintf(logbuffer, "  args->sleep_scaling_factor=%f", args->sleep_scaling_factor);
        log_entry(logbuffer, LVL_INFO);
-       sprintf(logbuffer, "  args->vacuum_base_threshold=%i", args->vacuum_base_threshold);
+       sprintf(logbuffer, "  args->vacuum_base_threshold=%d", args->vacuum_base_threshold);
        log_entry(logbuffer, LVL_INFO);
        sprintf(logbuffer, "  args->vacuum_scaling_factor=%f", args->vacuum_scaling_factor);
        log_entry(logbuffer, LVL_INFO);
-       sprintf(logbuffer, "  args->analyze_base_threshold=%i", args->analyze_base_threshold);
+       sprintf(logbuffer, "  args->analyze_base_threshold=%d", args->analyze_base_threshold);
        log_entry(logbuffer, LVL_INFO);
        sprintf(logbuffer, "  args->analyze_scaling_factor=%f", args->analyze_scaling_factor);
        log_entry(logbuffer, LVL_INFO);
-       sprintf(logbuffer, "  args->debug=%i", args->debug);
+       
+       if (args->av_vacuum_cost_delay != -1)
+               sprintf(logbuffer, "  args->av_vacuum_cost_delay=%d", args->av_vacuum_cost_delay);
+       else 
+               sprintf(logbuffer, "  args->av_vacuum_cost_delay=(default)");
+       log_entry(logbuffer, LVL_INFO);
+       if (args->av_vacuum_cost_page_hit != -1)
+               sprintf(logbuffer, "  args->av_vacuum_cost_page_hit=%d", args->av_vacuum_cost_page_hit);
+       else
+               sprintf(logbuffer, "  args->av_vacuum_cost_page_hit=(default)");
+       log_entry(logbuffer, LVL_INFO);
+       if (args->av_vacuum_cost_page_miss != -1)
+               sprintf(logbuffer, "  args->av_vacuum_cost_page_miss=%d", args->av_vacuum_cost_page_miss);
+       else
+               sprintf(logbuffer, "  args->av_vacuum_cost_page_miss=(default)");
+       log_entry(logbuffer, LVL_INFO);
+       if (args->av_vacuum_cost_page_dirty != -1)
+               sprintf(logbuffer, "  args->av_vacuum_cost_page_dirty=%d", args->av_vacuum_cost_page_dirty);
+       else
+               sprintf(logbuffer, "  args->av_vacuum_cost_page_dirty=(default)");
+       log_entry(logbuffer, LVL_INFO);
+       if (args->av_vacuum_cost_limit != -1)
+               sprintf(logbuffer, "  args->av_vacuum_cost_limit=%d", args->av_vacuum_cost_limit);
+       else
+               sprintf(logbuffer, "  args->av_vacuum_cost_limit=(default)");
+       log_entry(logbuffer, LVL_INFO);
+       
+       sprintf(logbuffer, "  args->debug=%d", args->debug);
        log_entry(logbuffer, LVL_INFO);
 
        fflush(LOGOUTPUT);
@@ -1285,20 +1412,30 @@ InstallService()
        if (args->logfile)
                sprintf(szCommand, "%s -L %s", szCommand, args->logfile);
        if (args->sleep_base_value != (int) SLEEPBASEVALUE)
-               sprintf(szCommand, "%s -s %i", szCommand, args->sleep_base_value);
+               sprintf(szCommand, "%s -s %d", szCommand, args->sleep_base_value);
        if (args->sleep_scaling_factor != (float) SLEEPSCALINGFACTOR)
                sprintf(szCommand, "%s -S %f", szCommand, args->sleep_scaling_factor);
        if (args->vacuum_base_threshold != (int) VACBASETHRESHOLD)
-               sprintf(szCommand, "%s -v %i", szCommand, args->vacuum_base_threshold);
+               sprintf(szCommand, "%s -v %d", szCommand, args->vacuum_base_threshold);
        if (args->vacuum_scaling_factor != (float) VACSCALINGFACTOR)
                sprintf(szCommand, "%s -V %f", szCommand, args->vacuum_scaling_factor);
        if (args->analyze_base_threshold != (int) (VACBASETHRESHOLD / 2))
-               sprintf(szCommand, "%s -a %i", szCommand, args->analyze_base_threshold);
+               sprintf(szCommand, "%s -a %d", szCommand, args->analyze_base_threshold);
        if (args->analyze_scaling_factor != (float) (VACSCALINGFACTOR / 2))
                sprintf(szCommand, "%s -A %f", szCommand, args->analyze_scaling_factor);
        if (args->debug != (int) AUTOVACUUM_DEBUG)
-               sprintf(szCommand, "%s -d %i", szCommand, args->debug);
-
+               sprintf(szCommand, "%s -d %d", szCommand, args->debug);
+       if (args->av_vacuum_cost_delay != -1)
+               sprintf(szCommand, "%s -d %d", szCommand, args->av_vacuum_cost_delay);
+       if (args->av_vacuum_cost_page_hit != -1)
+               sprintf(szCommand, "%s -d %d", szCommand, args->av_vacuum_cost_page_hit);
+       if (args->av_vacuum_cost_page_miss != -1)
+               sprintf(szCommand, "%s -d %d", szCommand, args->av_vacuum_cost_page_miss);
+       if (args->av_vacuum_cost_page_dirty != -1)
+               sprintf(szCommand, "%s -d %d", szCommand, args->av_vacuum_cost_page_dirty);
+       if (args->av_vacuum_cost_limit != -1)
+               sprintf(szCommand, "%s -d %d", szCommand, args->av_vacuum_cost_limit);          
+               
        /* And write the new value */
        if (RegSetValueEx(hk, "ImagePath", 0, REG_EXPAND_SZ, (LPBYTE) szCommand, (DWORD) strlen(szCommand) + 1))
                return -4;
@@ -1366,7 +1503,6 @@ static
 int
 VacuumLoop(int argc, char **argv)
 {
-       char            buf[256];
        int                     j = 0,
                                loops = 0;
 
@@ -1516,45 +1652,11 @@ VacuumLoop(int argc, char **argv)
                                                                         * analyze
                                                                         */
                                                                        if (tbl->curr_vacuum_count - tbl->CountAtLastVacuum >= tbl->vacuum_threshold)
-                                                                       {
-                                                                               /*
-                                                                                * if relisshared = t and database
-                                                                                * != template1 then only do an
-                                                                                * analyze
-                                                                                */
-                                                                               if (tbl->relisshared > 0 && strcmp("template1", dbs->dbname))
-                                                                                       snprintf(buf, sizeof(buf), "ANALYZE %s", tbl->table_name);
-                                                                               else
-                                                                                       snprintf(buf, sizeof(buf), "VACUUM ANALYZE %s", tbl->table_name);
-                                                                               if (args->debug >= 1)
-                                                                               {
-                                                                                       sprintf(logbuffer, "Performing: %s", buf);
-                                                                                       log_entry(logbuffer, LVL_DEBUG);
-                                                                                       fflush(LOGOUTPUT);
-                                                                               }
-                                                                               send_query(buf, dbs);
-                                                                               update_table_thresholds(dbs, tbl, VACUUM_ANALYZE);
-                                                                               if (args->debug >= 2)
-                                                                                       print_table_info(tbl);
-                                                                       }
+                                                                               perform_maintenance_command(dbs, tbl, VACUUM_ANALYZE);
                                                                        else if (tbl->curr_analyze_count - tbl->CountAtLastAnalyze >= tbl->analyze_threshold)
-                                                                       {
-                                                                               snprintf(buf, sizeof(buf), "ANALYZE %s", tbl->table_name);
-                                                                               if (args->debug >= 1)
-                                                                               {
-                                                                                       sprintf(logbuffer, "Performing: %s", buf);
-                                                                                       log_entry(logbuffer, LVL_DEBUG);
-                                                                                       fflush(LOGOUTPUT);
-                                                                               }
-                                                                               send_query(buf, dbs);
-                                                                               update_table_thresholds(dbs, tbl, ANALYZE_ONLY);
-                                                                               if (args->debug >= 2)
-                                                                                       print_table_info(tbl);
-                                                                       }
-
-                                                                       break;          /* once we have found a
-                                                                                                * match, no need to keep
-                                                                                                * checking. */
+                                                                               perform_maintenance_command(dbs, tbl, ANALYZE_ONLY);
+
+                                                                       break;          /* We found a match, no need to keep looping. */
                                                                }
 
                                                                /*
@@ -1566,7 +1668,7 @@ VacuumLoop(int argc, char **argv)
                                                        }       /* end for table while loop */
                                                }               /* end for j loop (tuples in PGresult) */
                                        }                       /* end if (res != NULL) */
-                               }                               /* close of if(xid_wraparound_check()) */
+                               }                               /* close of if (xid_wraparound_check()) */
                                /* Done working on this db, Clean up, then advance cur_db */
                                PQclear(res);
                                res = NULL;
@@ -1585,7 +1687,7 @@ VacuumLoop(int argc, char **argv)
                if (args->debug >= 2)
                {
                        sprintf(logbuffer,
-                        "%i All DBs checked in: %.0f usec, will sleep for %i secs.",
+                        "%d All DBs checked in: %.0f usec, will sleep for %d secs.",
                                        loops, diff, sleep_secs);
                        log_entry(logbuffer, LVL_DEBUG);
                        fflush(LOGOUTPUT);
index c903e97f2ccf8706e9df8081922aa95583ee08fd..02933fbc82dcdcc7dbf9c3ef621ceffcba0e5cbc 100644 (file)
@@ -2,7 +2,7 @@
  * Header file for pg_autovacuum.c
  * (c) 2003 Matthew T. O'Connor
  *
- * $PostgreSQL: pgsql/contrib/pg_autovacuum/pg_autovacuum.h,v 1.12 2004/10/16 21:50:02 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/pg_autovacuum/pg_autovacuum.h,v 1.13 2004/11/17 16:54:15 tgl Exp $
  */
 
 #ifndef _PG_AUTOVACUUM_H
@@ -46,6 +46,16 @@ typedef struct cmdargs
                                analyze_base_threshold,
                                sleep_base_value,
                                debug,
+                               
+                               /*
+                                * Cost-Based Vacuum Delay Settings for pg_autovacuum
+                                */
+                               av_vacuum_cost_delay,
+                               av_vacuum_cost_page_hit,
+                               av_vacuum_cost_page_miss,
+                               av_vacuum_cost_page_dirty,
+                               av_vacuum_cost_limit,
+                               
 #ifndef WIN32
                                daemonize;
 #else