On Wed, Oct 9, 2013 at 09:52:03AM -0700, Josh Berkus wrote: > On 10/09/2013 09:30 AM, Stephen Frost wrote: > >>> I went with shared_buffers because unlike the others, it is a fixed > >>> > > allocation quantity, while the other are much more variable and harder > >>> > > to set. I figured we could keep our 25% estimate of shared_buffers > >>> > > and > >>> > > everything else would fall in line. > >>> > > > >> > > >> > I understand, but your proposal change a logic to opposite direction. > >> > Maybe > >> > better is wait to new GUC parameter, and then implement this feature, so > >> > be > >> > logical and simply understandable. > > I disagree- having a better default than what we have now is going to > > almost certainly be a huge improvement in the vast majority of cases. > > How we arrive at the default isn't particularly relevant as long as we > > document it. Users who end up using the default don't do so because > > they read the docs and said "oh, yeah, the way they calculated the > > default makes a lot of sense", then end up using it because they never > > open the config file, at all. > > FWIW, I've been using the following calculations as "starting points" > for work_mem with both clients and students. In 80-90% of cases, the > user never adjusts the thresholds again, so I'd say that passes the test > for a "good enough" setting.
OK, I have developed the attached patch based on feedback. I took into account Andrew's concern that pooling might cause use of more work_mem than you would expect in a typical session, and Robert's legitimate concern about a destabalizing default for work_mem. I therefore went with the shared_buffers/4 idea. Josh had some interesting calculations for work_mem, but I didn't think the max value would work well as it would confuse users and not be properly maintained by us as hardware grew. I also think changing those defaults between major releases would be perhaps destabilizing. Josh's observation that he rarely sees more than 3x work_mem in a session helps put an upper limit on memory usage. I did like Josh's idea about using autovacuum_max_workers for maintenance_work_mem, though I used the shared_buffers/4 calculation. Here are the defaults for two configurations; first, for the 128MB default shared_buffers: test=> SHOW shared_buffers; shared_buffers ---------------- 128MB (1 row) test=> SHOW work_mem; work_mem ---------- 1095kB (1 row) test=> SHOW maintenance_work_mem; maintenance_work_mem ---------------------- 10922kB (1 row) and for shared_buffers of 2GB: test=> show shared_buffers; shared_buffers ---------------- 2GB (1 row) test=> SHOW work_mem; work_mem ---------- 6010kB (1 row) test=> SHOW maintenance_work_mem ; maintenance_work_mem ---------------------- 174762kB (1 row) -- Bruce Momjian <br...@momjian.us> http://momjian.us EnterpriseDB http://enterprisedb.com + Everyone has their own god. +
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml new file mode 100644 index e8e8e6f..31f1265 *** a/doc/src/sgml/config.sgml --- b/doc/src/sgml/config.sgml *************** include 'filename' *** 1121,1127 **** <para> Specifies the amount of memory to be used by internal sort operations and hash tables before writing to temporary disk files. The value ! defaults to one megabyte (<literal>1MB</>). Note that for a complex query, several sort or hash operations might be running in parallel; each operation will be allowed to use as much memory as this value specifies before it starts to write data into temporary --- 1121,1128 ---- <para> Specifies the amount of memory to be used by internal sort operations and hash tables before writing to temporary disk files. The value ! defaults to <varname>shared_buffers</> / 4 / ! <varname>max_connections</> + 768kB. Note that for a complex query, several sort or hash operations might be running in parallel; each operation will be allowed to use as much memory as this value specifies before it starts to write data into temporary *************** include 'filename' *** 1147,1153 **** Specifies the maximum amount of memory to be used by maintenance operations, such as <command>VACUUM</command>, <command>CREATE INDEX</>, and <command>ALTER TABLE ADD FOREIGN KEY</>. It defaults ! to 16 megabytes (<literal>16MB</>). Since only one of these operations can be executed at a time by a database session, and an installation normally doesn't have many of them running concurrently, it's safe to set this value significantly larger --- 1148,1155 ---- Specifies the maximum amount of memory to be used by maintenance operations, such as <command>VACUUM</command>, <command>CREATE INDEX</>, and <command>ALTER TABLE ADD FOREIGN KEY</>. It defaults ! to <varname>shared_buffers</> / 4 / ! <varname>autovacuum_max_workers</>. Since only one of these operations can be executed at a time by a database session, and an installation normally doesn't have many of them running concurrently, it's safe to set this value significantly larger diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c new file mode 100644 index 33efb3c..68af1dc *** a/src/backend/utils/init/globals.c --- b/src/backend/utils/init/globals.c *************** int CTimeZone = 0; *** 98,105 **** bool enableFsync = true; bool allowSystemTableMods = false; ! int work_mem = 1024; ! int maintenance_work_mem = 16384; /* * Primary determinants of sizes of shared-memory structures. --- 98,105 ---- bool enableFsync = true; bool allowSystemTableMods = false; ! int work_mem = -1; ! int maintenance_work_mem = -1; /* * Primary determinants of sizes of shared-memory structures. diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c new file mode 100644 index ddbeb34..29b1943 *** a/src/backend/utils/misc/guc.c --- b/src/backend/utils/misc/guc.c *************** *** 117,122 **** --- 117,125 ---- #define S_PER_D (60 * 60 * 24) #define MS_PER_D (1000 * 60 * 60 * 24) + /* This is the minimum added for auto-tuning of work_mem */ + #define WORK_MEM_ADDITION_kB 768 + /* XXX these should appear in other modules' header files */ extern bool Log_disconnections; extern int CommitDelay; *************** static struct config_int ConfigureNamesI *** 1720,1727 **** GUC_UNIT_KB }, &work_mem, ! 1024, 64, MAX_KILOBYTES, ! NULL, NULL, NULL }, { --- 1723,1730 ---- GUC_UNIT_KB }, &work_mem, ! -1, -1, MAX_KILOBYTES, ! check_work_mem, NULL, NULL }, { *************** static struct config_int ConfigureNamesI *** 1731,1738 **** GUC_UNIT_KB }, &maintenance_work_mem, ! 16384, 1024, MAX_KILOBYTES, ! NULL, NULL, NULL }, /* --- 1734,1741 ---- GUC_UNIT_KB }, &maintenance_work_mem, ! -1, -1, MAX_KILOBYTES, ! check_maintenance_work_mem, NULL, NULL }, /* *************** SelectConfigFiles(const char *userDoptio *** 4239,4245 **** pg_timezone_abbrev_initialize(); set_default_effective_cache_size(); ! /* * Figure out where pg_hba.conf is, and make sure the path is absolute. */ --- 4242,4249 ---- pg_timezone_abbrev_initialize(); set_default_effective_cache_size(); ! set_default_work_mems(); ! /* * Figure out where pg_hba.conf is, and make sure the path is absolute. */ *************** show_log_file_mode(void) *** 8886,8889 **** --- 8890,8984 ---- return buf; } + void + set_default_work_mems(void) + { + /* + * If the value of work_mem is -1, use the preferred + * auto-tune value. + */ + if (work_mem == -1) + { + char buf[32]; + + snprintf(buf, sizeof(buf), "%ld", ((NBuffers / 4) * BLCKSZ / 1024L) / + MaxConnections + WORK_MEM_ADDITION_kB); + SetConfigOption("work_mem", buf, PGC_POSTMASTER, PGC_S_OVERRIDE); + } + Assert(work_mem > 0); + + if (maintenance_work_mem == -1) + { + char buf[32]; + + snprintf(buf, sizeof(buf), "%ld", ((NBuffers / 4) * BLCKSZ / 1024L) / + autovacuum_max_workers); + SetConfigOption("maintenance_work_mem", buf, PGC_POSTMASTER, PGC_S_OVERRIDE); + } + Assert(maintenance_work_mem > 0); + } + + /* + * GUC check_hook for work_mem + */ + bool + check_work_mem(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 later. + */ + if (work_mem == -1) + return true; + + /* Otherwise, substitute the auto-tune value */ + *newval = ((NBuffers / 4) * BLCKSZ / 1024L) / MaxConnections + + WORK_MEM_ADDITION_kB; + } + + /* set minimum? check maximum? */ + if (*newval < 64) + *newval = 64; + if (*newval > MAX_KILOBYTES) + *newval = MAX_KILOBYTES; + + return true; + } + + /* + * GUC check_hook for maintenance_work_mem + */ + bool + check_maintenance_work_mem(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 later. + */ + if (maintenance_work_mem == -1) + return true; + + /* Otherwise, substitute the auto-tune value */ + *newval = ((NBuffers / 4) * BLCKSZ / 1024L) / autovacuum_max_workers; + } + + /* set minimum? check maximum? */ + if (*newval < 1024) + *newval = 1024; + if (*newval > MAX_KILOBYTES) + *newval = MAX_KILOBYTES; + + return true; + } + #include "guc-file.c" diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample new file mode 100644 index 70221f4..a8da95b *** a/src/backend/utils/misc/postgresql.conf.sample --- b/src/backend/utils/misc/postgresql.conf.sample *************** *** 120,127 **** # per transaction slot, plus lock space (see max_locks_per_transaction). # It is not advisable to set max_prepared_transactions nonzero unless you # actively intend to use prepared transactions. ! #work_mem = 1MB # min 64kB ! #maintenance_work_mem = 16MB # min 1MB #max_stack_depth = 2MB # min 100kB # - Disk - --- 120,127 ---- # per transaction slot, plus lock space (see max_locks_per_transaction). # It is not advisable to set max_prepared_transactions nonzero unless you # actively intend to use prepared transactions. ! #work_mem = -1 # min 64kB ! #maintenance_work_mem = -1 # min 1MB #max_stack_depth = 2MB # min 100kB # - Disk - diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h new file mode 100644 index 3e981b3..f696eed *** a/src/include/utils/guc.h --- b/src/include/utils/guc.h *************** extern void assign_search_path(const cha *** 388,393 **** --- 388,396 ---- 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 bool check_work_mem(int *newval, void **extra, GucSource source); + extern bool check_maintenance_work_mem(int *newval, void **extra, GucSource source); + extern void set_default_work_mems(void); extern void assign_xlog_sync_method(int new_sync_method, void *extra); #endif /* GUC_H */
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers