Introduce a maintenance_io_concurrency setting.
Introduce a GUC and a tablespace option to control I/O prefetching, much like effective_io_concurrency, but for work that is done on behalf of many client sessions. Use the new setting in heapam.c instead of the hard-coded formula effective_io_concurrency + 10 introduced by commit 558a9165e08. Go with a default value of 10 for now, because it's a round number pretty close to the value used for that existing case. Discussion: https://postgr.es/m/CA%2BhUKGJUw08dPs_3EUcdO6M90GnjofPYrWp4YSLaBkgYwS-AqA%40mail.gmail.com
This commit is contained in:
parent
b09ff53667
commit
fc34b0d9de
@ -2229,6 +2229,26 @@ include_dir 'conf.d'
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry id="guc-maintenance-io-concurrency" xreflabel="maintenance_io_concurrency">
|
||||
<term><varname>maintenance_io_concurrency</varname> (<type>integer</type>)
|
||||
<indexterm>
|
||||
<primary><varname>maintenance_io_concurrency</varname> configuration parameter</primary>
|
||||
</indexterm>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Similar to <varname>effective_io_concurrency</varname>, but used
|
||||
for maintenance work that is done on behalf of many client sessions.
|
||||
</para>
|
||||
<para>
|
||||
The default is 10 on supported systems, otherwise 0. This value can
|
||||
be overridden for tables in a particular tablespace by setting the
|
||||
tablespace parameter of the same name (see
|
||||
<xref linkend="sql-altertablespace"/>).
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry id="guc-max-worker-processes" xreflabel="max_worker_processes">
|
||||
<term><varname>max_worker_processes</varname> (<type>integer</type>)
|
||||
<indexterm>
|
||||
|
@ -84,13 +84,16 @@ ALTER TABLESPACE <replaceable>name</replaceable> RESET ( <replaceable class="par
|
||||
<para>
|
||||
A tablespace parameter to be set or reset. Currently, the only
|
||||
available parameters are <varname>seq_page_cost</varname>,
|
||||
<varname>random_page_cost</varname> and <varname>effective_io_concurrency</varname>.
|
||||
Setting either value for a particular tablespace will override the
|
||||
<varname>random_page_cost</varname>, <varname>effective_io_concurrency</varname>
|
||||
and <varname>maintenance_io_concurrency</varname>.
|
||||
Setting these values for a particular tablespace will override the
|
||||
planner's usual estimate of the cost of reading pages from tables in
|
||||
that tablespace, as established by the configuration parameters of the
|
||||
that tablespace, and the executor's prefetching behavior, as established
|
||||
by the configuration parameters of the
|
||||
same name (see <xref linkend="guc-seq-page-cost"/>,
|
||||
<xref linkend="guc-random-page-cost"/>,
|
||||
<xref linkend="guc-effective-io-concurrency"/>). This may be useful if
|
||||
<xref linkend="guc-effective-io-concurrency"/>,
|
||||
<xref linkend="guc-maintenance-io-concurrency"/>). This may be useful if
|
||||
one tablespace is located on a disk which is faster or slower than the
|
||||
remainder of the I/O subsystem.
|
||||
</para>
|
||||
|
@ -106,13 +106,16 @@ CREATE TABLESPACE <replaceable class="parameter">tablespace_name</replaceable>
|
||||
<para>
|
||||
A tablespace parameter to be set or reset. Currently, the only
|
||||
available parameters are <varname>seq_page_cost</varname>,
|
||||
<varname>random_page_cost</varname> and <varname>effective_io_concurrency</varname>.
|
||||
Setting either value for a particular tablespace will override the
|
||||
<varname>random_page_cost</varname>, <varname>effective_io_concurrency</varname>
|
||||
and <varname>maintenance_io_concurrency</varname>.
|
||||
Setting these values for a particular tablespace will override the
|
||||
planner's usual estimate of the cost of reading pages from tables in
|
||||
that tablespace, as established by the configuration parameters of the
|
||||
that tablespace, and the executor's prefetching behavior, as established
|
||||
by the configuration parameters of the
|
||||
same name (see <xref linkend="guc-seq-page-cost"/>,
|
||||
<xref linkend="guc-random-page-cost"/>,
|
||||
<xref linkend="guc-effective-io-concurrency"/>). This may be useful if
|
||||
<xref linkend="guc-effective-io-concurrency"/>,
|
||||
<xref linkend="guc-maintenance-io-concurrency"/>). This may be useful if
|
||||
one tablespace is located on a disk which is faster or slower than the
|
||||
remainder of the I/O subsystem.
|
||||
</para>
|
||||
|
@ -349,6 +349,19 @@ static relopt_int intRelOpts[] =
|
||||
-1, 0, MAX_IO_CONCURRENCY
|
||||
#else
|
||||
0, 0, 0
|
||||
#endif
|
||||
},
|
||||
{
|
||||
{
|
||||
"maintenance_io_concurrency",
|
||||
"Number of simultaneous requests that can be handled efficiently by the disk subsystem for maintenance work.",
|
||||
RELOPT_KIND_TABLESPACE,
|
||||
ShareUpdateExclusiveLock
|
||||
},
|
||||
#ifdef USE_PREFETCH
|
||||
-1, 0, MAX_IO_CONCURRENCY
|
||||
#else
|
||||
0, 0, 0
|
||||
#endif
|
||||
},
|
||||
{
|
||||
@ -1700,7 +1713,8 @@ tablespace_reloptions(Datum reloptions, bool validate)
|
||||
static const relopt_parse_elt tab[] = {
|
||||
{"random_page_cost", RELOPT_TYPE_REAL, offsetof(TableSpaceOpts, random_page_cost)},
|
||||
{"seq_page_cost", RELOPT_TYPE_REAL, offsetof(TableSpaceOpts, seq_page_cost)},
|
||||
{"effective_io_concurrency", RELOPT_TYPE_INT, offsetof(TableSpaceOpts, effective_io_concurrency)}
|
||||
{"effective_io_concurrency", RELOPT_TYPE_INT, offsetof(TableSpaceOpts, effective_io_concurrency)},
|
||||
{"maintenance_io_concurrency", RELOPT_TYPE_INT, offsetof(TableSpaceOpts, maintenance_io_concurrency)}
|
||||
};
|
||||
|
||||
return (bytea *) build_reloptions(reloptions, validate,
|
||||
|
@ -7003,7 +7003,6 @@ heap_compute_xid_horizon_for_tuples(Relation rel,
|
||||
Page hpage;
|
||||
#ifdef USE_PREFETCH
|
||||
XidHorizonPrefetchState prefetch_state;
|
||||
int io_concurrency;
|
||||
int prefetch_distance;
|
||||
#endif
|
||||
|
||||
@ -7026,24 +7025,15 @@ heap_compute_xid_horizon_for_tuples(Relation rel,
|
||||
/*
|
||||
* Compute the prefetch distance that we will attempt to maintain.
|
||||
*
|
||||
* We don't use the regular formula to determine how much to prefetch
|
||||
* here, but instead just add a constant to effective_io_concurrency.
|
||||
* That's because it seems best to do some prefetching here even when
|
||||
* effective_io_concurrency is set to 0, but if the DBA thinks it's OK to
|
||||
* do more prefetching for other operations, then it's probably OK to do
|
||||
* more prefetching in this case, too. It may be that this formula is too
|
||||
* simplistic, but at the moment there is no evidence of that or any idea
|
||||
* about what would work better.
|
||||
*
|
||||
* Since the caller holds a buffer lock somewhere in rel, we'd better make
|
||||
* sure that isn't a catalog relation before we call code that does
|
||||
* syscache lookups, to avoid risk of deadlock.
|
||||
*/
|
||||
if (IsCatalogRelation(rel))
|
||||
io_concurrency = effective_io_concurrency;
|
||||
prefetch_distance = maintenance_io_concurrency;
|
||||
else
|
||||
io_concurrency = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
|
||||
prefetch_distance = Min((io_concurrency) + 10, MAX_IO_CONCURRENCY);
|
||||
prefetch_distance =
|
||||
get_tablespace_maintenance_io_concurrency(rel->rd_rel->reltablespace);
|
||||
|
||||
/* Start prefetching. */
|
||||
xid_horizon_prefetch_buffer(rel, &prefetch_state, prefetch_distance);
|
||||
|
@ -119,6 +119,13 @@ bool track_io_timing = false;
|
||||
*/
|
||||
int effective_io_concurrency = 0;
|
||||
|
||||
/*
|
||||
* Like effective_io_concurrency, but used by maintenance code paths that might
|
||||
* benefit from a higher setting because they work on behalf of many sessions.
|
||||
* Overridden by the tablespace setting of the same name.
|
||||
*/
|
||||
int maintenance_io_concurrency = 0;
|
||||
|
||||
/*
|
||||
* GUC variables about triggering kernel writeback for buffers written; OS
|
||||
* dependent defaults are set via the GUC mechanism.
|
||||
|
14
src/backend/utils/cache/spccache.c
vendored
14
src/backend/utils/cache/spccache.c
vendored
@ -221,3 +221,17 @@ get_tablespace_io_concurrency(Oid spcid)
|
||||
else
|
||||
return spc->opts->effective_io_concurrency;
|
||||
}
|
||||
|
||||
/*
|
||||
* get_tablespace_maintenance_io_concurrency
|
||||
*/
|
||||
int
|
||||
get_tablespace_maintenance_io_concurrency(Oid spcid)
|
||||
{
|
||||
TableSpaceCacheEntry *spc = get_tablespace(spcid);
|
||||
|
||||
if (!spc->opts || spc->opts->maintenance_io_concurrency < 0)
|
||||
return maintenance_io_concurrency;
|
||||
else
|
||||
return spc->opts->maintenance_io_concurrency;
|
||||
}
|
||||
|
@ -196,6 +196,7 @@ static bool check_autovacuum_max_workers(int *newval, void **extra, GucSource so
|
||||
static bool check_max_wal_senders(int *newval, void **extra, GucSource source);
|
||||
static bool check_autovacuum_work_mem(int *newval, void **extra, GucSource source);
|
||||
static bool check_effective_io_concurrency(int *newval, void **extra, GucSource source);
|
||||
static bool check_maintenance_io_concurrency(int *newval, void **extra, GucSource source);
|
||||
static void assign_pgstat_temp_directory(const char *newval, void *extra);
|
||||
static bool check_application_name(char **newval, void **extra, GucSource source);
|
||||
static void assign_application_name(const char *newval, void *extra);
|
||||
@ -2884,6 +2885,24 @@ static struct config_int ConfigureNamesInt[] =
|
||||
check_effective_io_concurrency, NULL, NULL
|
||||
},
|
||||
|
||||
{
|
||||
{"maintenance_io_concurrency",
|
||||
PGC_USERSET,
|
||||
RESOURCES_ASYNCHRONOUS,
|
||||
gettext_noop("A variant of effective_io_concurrency that is used for maintenance work."),
|
||||
NULL,
|
||||
GUC_EXPLAIN
|
||||
},
|
||||
&maintenance_io_concurrency,
|
||||
#ifdef USE_PREFETCH
|
||||
10,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
0, MAX_IO_CONCURRENCY,
|
||||
check_maintenance_io_concurrency, NULL, NULL
|
||||
},
|
||||
|
||||
{
|
||||
{"backend_flush_after", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
|
||||
gettext_noop("Number of pages after which previously performed writes are flushed to disk."),
|
||||
@ -11466,6 +11485,19 @@ check_effective_io_concurrency(int *newval, void **extra, GucSource source)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
check_maintenance_io_concurrency(int *newval, void **extra, GucSource source)
|
||||
{
|
||||
#ifndef USE_PREFETCH
|
||||
if (*newval != 0)
|
||||
{
|
||||
GUC_check_errdetail("maintenance_io_concurrency must be set to 0 on platforms that lack posix_fadvise().");
|
||||
return false;
|
||||
}
|
||||
#endif /* USE_PREFETCH */
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
assign_pgstat_temp_directory(const char *newval, void *extra)
|
||||
{
|
||||
|
@ -2140,7 +2140,7 @@ psql_completion(const char *text, int start, int end)
|
||||
/* ALTER TABLESPACE <foo> SET|RESET ( */
|
||||
else if (Matches("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
|
||||
COMPLETE_WITH("seq_page_cost", "random_page_cost",
|
||||
"effective_io_concurrency");
|
||||
"effective_io_concurrency", "maintenance_io_concurrency");
|
||||
|
||||
/* ALTER TEXT SEARCH */
|
||||
else if (Matches("ALTER", "TEXT", "SEARCH"))
|
||||
|
@ -40,6 +40,7 @@ typedef struct TableSpaceOpts
|
||||
float8 random_page_cost;
|
||||
float8 seq_page_cost;
|
||||
int effective_io_concurrency;
|
||||
int maintenance_io_concurrency;
|
||||
} TableSpaceOpts;
|
||||
|
||||
extern Oid CreateTableSpace(CreateTableSpaceStmt *stmt);
|
||||
|
@ -58,6 +58,7 @@ extern int bgwriter_lru_maxpages;
|
||||
extern double bgwriter_lru_multiplier;
|
||||
extern bool track_io_timing;
|
||||
extern int effective_io_concurrency;
|
||||
extern int maintenance_io_concurrency;
|
||||
|
||||
extern int checkpoint_flush_after;
|
||||
extern int backend_flush_after;
|
||||
|
@ -16,5 +16,6 @@
|
||||
void get_tablespace_page_costs(Oid spcid, float8 *spc_random_page_cost,
|
||||
float8 *spc_seq_page_cost);
|
||||
int get_tablespace_io_concurrency(Oid spcid);
|
||||
int get_tablespace_maintenance_io_concurrency(Oid spcid);
|
||||
|
||||
#endif /* SPCCACHE_H */
|
||||
|
Loading…
x
Reference in New Issue
Block a user