Auto-tune effective_cache size to be 4x shared buffers
authorBruce Momjian <bruce@momjian.us>
Tue, 8 Oct 2013 16:12:24 +0000 (12:12 -0400)
committerBruce Momjian <bruce@momjian.us>
Tue, 8 Oct 2013 16:12:24 +0000 (12:12 -0400)
doc/src/sgml/config.sgml
src/backend/optimizer/path/costsize.c
src/backend/postmaster/postmaster.c
src/backend/utils/misc/guc.c
src/include/optimizer/cost.h
src/include/utils/guc.h
src/test/regress/expected/join.out
src/test/regress/sql/join.sql

index 697cf401374758e47eb174a3f22b451b20e0f272..116acd7eca14e259e00fed747170261be220ecd1 100644 (file)
@@ -2758,7 +2758,7 @@ include 'filename'
 
        <para>
         Random access to mechanical disk storage is normally much more expensive
-        than four-times sequential access.  However, a lower default is used
+        than four times sequential access.  However, a lower default is used
         (4.0) because the majority of random accesses to disk, such as indexed
         reads, are assumed to be in cache.  The default value can be thought of
         as modeling random access as 40 times slower than sequential, while
@@ -2841,9 +2841,17 @@ include 'filename'
       <listitem>
        <para>
         Sets the planner's assumption about the effective size of the
-        disk cache that is available to a single query.  This is
-        factored into estimates of the cost of using an index; a
-        higher value makes it more likely index scans will be used, a
+        disk cache that is available to a single query.  The default
+        setting of -1 selects a size equal to four times the size of <xref
+        linkend="guc-shared-buffers">, but not less than the size of one
+        shared buffer page, typically <literal>8kB</literal>.  This value
+        can be set manually if the automatic choice is too large or too
+        small.
+       </para>
+
+       <para>
+        This value is factored into estimates of the cost of using an index;
+        a higher value makes it more likely index scans will be used, a
         lower value makes it more likely sequential scans will be
         used. When setting this parameter you should consider both
         <productname>PostgreSQL</productname>'s shared buffers and the
@@ -2855,8 +2863,10 @@ include 'filename'
         memory allocated by <productname>PostgreSQL</productname>, nor
         does it reserve kernel disk cache; it is used only for estimation
         purposes.  The system also does not assume data remains in
-        the disk cache between queries.  The default is 128 megabytes
-        (<literal>128MB</>).
+        the disk cache between queries.  The auto-tuning
+        selected by the default setting of -1 should give reasonable
+        results if this database cluster is can utilize most of the memory
+        on this server.
        </para>
       </listitem>
      </varlistentry>
index 0caac75ac5aa441df9286ccb44c3bed2279c5a99..82c66f76caf39e96c509f285d123d33fe8b2a6e7 100644 (file)
@@ -87,6 +87,7 @@
 #include "optimizer/planmain.h"
 #include "optimizer/restrictinfo.h"
 #include "parser/parsetree.h"
+#include "utils/guc.h"
 #include "utils/lsyscache.h"
 #include "utils/selfuncs.h"
 #include "utils/spccache.h"
 
 #define LOG2(x)  (log(x) / 0.693147180559945)
 
-
 double     seq_page_cost = DEFAULT_SEQ_PAGE_COST;
 double     random_page_cost = DEFAULT_RANDOM_PAGE_COST;
 double     cpu_tuple_cost = DEFAULT_CPU_TUPLE_COST;
 double     cpu_index_tuple_cost = DEFAULT_CPU_INDEX_TUPLE_COST;
 double     cpu_operator_cost = DEFAULT_CPU_OPERATOR_COST;
 
-int            effective_cache_size = DEFAULT_EFFECTIVE_CACHE_SIZE;
+int            effective_cache_size = -1;
 
 Cost       disable_cost = 1.0e10;
 
@@ -456,6 +456,52 @@ cost_index(IndexPath *path, PlannerInfo *root, double loop_count)
    path->path.total_cost = startup_cost + run_cost;
 }
 
+void
+set_default_effective_cache_size(void)
+{
+   /*
+    * If the value of effective_cache_size is -1, use the preferred
+    * auto-tune value.
+    */
+   if (effective_cache_size == -1)
+   {
+       char        buf[32];
+
+       snprintf(buf, sizeof(buf), "%d", NBuffers * DEFAULT_EFFECTIVE_CACHE_SIZE_MULTI);
+       SetConfigOption("effective_cache_size", buf, PGC_POSTMASTER, PGC_S_OVERRIDE);
+   }
+   Assert(effective_cache_size > 0);
+}
+
+/*
+ * GUC check_hook for effective_cache_size
+ */
+bool
+check_effective_cache_size(int *newval, void **extra, GucSource source)
+{
+   /*
+    * -1 indicates a request for auto-tune.
+    */
+   if (*newval == -1)
+   {
+       /*
+        * If we haven't yet changed the boot_val default of -1, just let it
+        * be.  We'll fix it in index_pages_fetched
+        */
+       if (effective_cache_size == -1)
+           return true;
+
+       /* Otherwise, substitute the auto-tune value */
+       *newval = NBuffers * DEFAULT_EFFECTIVE_CACHE_SIZE_MULTI;
+   }
+
+   /* set minimum? */
+   if (*newval < 1)
+       *newval = 1;
+
+   return true;
+}
+
 /*
  * index_pages_fetched
  *   Estimate the number of pages actually fetched after accounting for
index 9f721b76515ca0c729568dda0ec6914584874a8c..c4b54d12cb29624171a62a095ec67e5d1d6ae97d 100644 (file)
 #include "utils/builtins.h"
 #include "utils/datetime.h"
 #include "utils/dynamic_loader.h"
+#include "utils/guc.h"
 #include "utils/memutils.h"
 #include "utils/ps_status.h"
 #include "utils/timeout.h"
@@ -4475,6 +4476,8 @@ SubPostmasterMain(int argc, char *argv[])
    memset(&port, 0, sizeof(Port));
    read_backend_variables(argv[2], &port);
 
+   set_default_effective_cache_size();
+
    /*
     * Set reference point for stack-depth checking
     */
index d9a06b4d881bdbe7b71edfedc2f65e8c1b48be38..833f34b1ee28ac7bc12684313b3b02d4e0f5f27e 100644 (file)
@@ -2410,8 +2410,8 @@ static struct config_int ConfigureNamesInt[] =
            GUC_UNIT_BLOCKS,
        },
        &effective_cache_size,
-       DEFAULT_EFFECTIVE_CACHE_SIZE, 1, INT_MAX,
-       NULL, NULL, NULL
+       -1, -1, INT_MAX,
+       check_effective_cache_size, NULL, NULL
    },
 
    {
index a052944d10c798a6a680796f86dba591e0a5103b..444ab7404435417b713fbba1e3e17ca61221c35e 100644 (file)
@@ -27,7 +27,7 @@
 #define DEFAULT_CPU_INDEX_TUPLE_COST 0.005
 #define DEFAULT_CPU_OPERATOR_COST  0.0025
 
-#define DEFAULT_EFFECTIVE_CACHE_SIZE  16384        /* measured in pages */
+#define DEFAULT_EFFECTIVE_CACHE_SIZE_MULTI 4
 
 typedef enum
 {
index 89ee40c334a1eddd9a945f33d011c170a45a07a4..3e981b3e94b4ce2f6eb3ecc1323ec006f4c85ee7 100644 (file)
@@ -386,6 +386,8 @@ extern void assign_search_path(const char *newval, void *extra);
 
 /* in access/transam/xlog.c */
 extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
+extern bool check_effective_cache_size(int *newval, void **extra, GucSource source);
+extern void set_default_effective_cache_size(void);
 extern void assign_xlog_sync_method(int new_sync_method, void *extra);
 
 #endif   /* GUC_H */
index c94ac614af8719918b14cd09780f51939ba9a7f8..d46ff26d82b46be00a8a87916630f69bdc949011 100644 (file)
@@ -2713,6 +2713,7 @@ where thousand = (q1 + q2);
 --
 -- test placement of movable quals in a parameterized join tree
 --
+set effective_cache_size = '128MB';
 explain (costs off)
 select * from tenk1 t1 left join
   (tenk1 t2 join tenk1 t3 on t2.thousand = t3.unique2)
index 351400f2da2ff2f8185bab9bd40880a782a76e1a..1a4dc03d18babd2a0b52af18ff201d7caf552d2a 100644 (file)
@@ -711,6 +711,8 @@ where thousand = (q1 + q2);
 -- test placement of movable quals in a parameterized join tree
 --
 
+set effective_cache_size = '128MB';
+
 explain (costs off)
 select * from tenk1 t1 left join
   (tenk1 t2 join tenk1 t3 on t2.thousand = t3.unique2)