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>
|
</listitem>
|
||||||
</varlistentry>
|
</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">
|
<varlistentry id="guc-max-worker-processes" xreflabel="max_worker_processes">
|
||||||
<term><varname>max_worker_processes</varname> (<type>integer</type>)
|
<term><varname>max_worker_processes</varname> (<type>integer</type>)
|
||||||
<indexterm>
|
<indexterm>
|
||||||
|
@ -84,13 +84,16 @@ ALTER TABLESPACE <replaceable>name</replaceable> RESET ( <replaceable class="par
|
|||||||
<para>
|
<para>
|
||||||
A tablespace parameter to be set or reset. Currently, the only
|
A tablespace parameter to be set or reset. Currently, the only
|
||||||
available parameters are <varname>seq_page_cost</varname>,
|
available parameters are <varname>seq_page_cost</varname>,
|
||||||
<varname>random_page_cost</varname> and <varname>effective_io_concurrency</varname>.
|
<varname>random_page_cost</varname>, <varname>effective_io_concurrency</varname>
|
||||||
Setting either value for a particular tablespace will override the
|
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
|
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"/>,
|
same name (see <xref linkend="guc-seq-page-cost"/>,
|
||||||
<xref linkend="guc-random-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
|
one tablespace is located on a disk which is faster or slower than the
|
||||||
remainder of the I/O subsystem.
|
remainder of the I/O subsystem.
|
||||||
</para>
|
</para>
|
||||||
|
@ -106,13 +106,16 @@ CREATE TABLESPACE <replaceable class="parameter">tablespace_name</replaceable>
|
|||||||
<para>
|
<para>
|
||||||
A tablespace parameter to be set or reset. Currently, the only
|
A tablespace parameter to be set or reset. Currently, the only
|
||||||
available parameters are <varname>seq_page_cost</varname>,
|
available parameters are <varname>seq_page_cost</varname>,
|
||||||
<varname>random_page_cost</varname> and <varname>effective_io_concurrency</varname>.
|
<varname>random_page_cost</varname>, <varname>effective_io_concurrency</varname>
|
||||||
Setting either value for a particular tablespace will override the
|
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
|
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"/>,
|
same name (see <xref linkend="guc-seq-page-cost"/>,
|
||||||
<xref linkend="guc-random-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
|
one tablespace is located on a disk which is faster or slower than the
|
||||||
remainder of the I/O subsystem.
|
remainder of the I/O subsystem.
|
||||||
</para>
|
</para>
|
||||||
|
@ -349,6 +349,19 @@ static relopt_int intRelOpts[] =
|
|||||||
-1, 0, MAX_IO_CONCURRENCY
|
-1, 0, MAX_IO_CONCURRENCY
|
||||||
#else
|
#else
|
||||||
0, 0, 0
|
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
|
#endif
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1700,7 +1713,8 @@ tablespace_reloptions(Datum reloptions, bool validate)
|
|||||||
static const relopt_parse_elt tab[] = {
|
static const relopt_parse_elt tab[] = {
|
||||||
{"random_page_cost", RELOPT_TYPE_REAL, offsetof(TableSpaceOpts, random_page_cost)},
|
{"random_page_cost", RELOPT_TYPE_REAL, offsetof(TableSpaceOpts, random_page_cost)},
|
||||||
{"seq_page_cost", RELOPT_TYPE_REAL, offsetof(TableSpaceOpts, seq_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,
|
return (bytea *) build_reloptions(reloptions, validate,
|
||||||
|
@ -7003,7 +7003,6 @@ heap_compute_xid_horizon_for_tuples(Relation rel,
|
|||||||
Page hpage;
|
Page hpage;
|
||||||
#ifdef USE_PREFETCH
|
#ifdef USE_PREFETCH
|
||||||
XidHorizonPrefetchState prefetch_state;
|
XidHorizonPrefetchState prefetch_state;
|
||||||
int io_concurrency;
|
|
||||||
int prefetch_distance;
|
int prefetch_distance;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -7026,24 +7025,15 @@ heap_compute_xid_horizon_for_tuples(Relation rel,
|
|||||||
/*
|
/*
|
||||||
* Compute the prefetch distance that we will attempt to maintain.
|
* 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
|
* 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
|
* sure that isn't a catalog relation before we call code that does
|
||||||
* syscache lookups, to avoid risk of deadlock.
|
* syscache lookups, to avoid risk of deadlock.
|
||||||
*/
|
*/
|
||||||
if (IsCatalogRelation(rel))
|
if (IsCatalogRelation(rel))
|
||||||
io_concurrency = effective_io_concurrency;
|
prefetch_distance = maintenance_io_concurrency;
|
||||||
else
|
else
|
||||||
io_concurrency = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
|
prefetch_distance =
|
||||||
prefetch_distance = Min((io_concurrency) + 10, MAX_IO_CONCURRENCY);
|
get_tablespace_maintenance_io_concurrency(rel->rd_rel->reltablespace);
|
||||||
|
|
||||||
/* Start prefetching. */
|
/* Start prefetching. */
|
||||||
xid_horizon_prefetch_buffer(rel, &prefetch_state, prefetch_distance);
|
xid_horizon_prefetch_buffer(rel, &prefetch_state, prefetch_distance);
|
||||||
|
@ -119,6 +119,13 @@ bool track_io_timing = false;
|
|||||||
*/
|
*/
|
||||||
int effective_io_concurrency = 0;
|
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
|
* GUC variables about triggering kernel writeback for buffers written; OS
|
||||||
* dependent defaults are set via the GUC mechanism.
|
* 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
|
else
|
||||||
return spc->opts->effective_io_concurrency;
|
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_max_wal_senders(int *newval, void **extra, GucSource source);
|
||||||
static bool check_autovacuum_work_mem(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_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 void assign_pgstat_temp_directory(const char *newval, void *extra);
|
||||||
static bool check_application_name(char **newval, void **extra, GucSource source);
|
static bool check_application_name(char **newval, void **extra, GucSource source);
|
||||||
static void assign_application_name(const char *newval, void *extra);
|
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
|
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,
|
{"backend_flush_after", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
|
||||||
gettext_noop("Number of pages after which previously performed writes are flushed to disk."),
|
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;
|
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
|
static void
|
||||||
assign_pgstat_temp_directory(const char *newval, void *extra)
|
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 ( */
|
/* ALTER TABLESPACE <foo> SET|RESET ( */
|
||||||
else if (Matches("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
|
else if (Matches("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
|
||||||
COMPLETE_WITH("seq_page_cost", "random_page_cost",
|
COMPLETE_WITH("seq_page_cost", "random_page_cost",
|
||||||
"effective_io_concurrency");
|
"effective_io_concurrency", "maintenance_io_concurrency");
|
||||||
|
|
||||||
/* ALTER TEXT SEARCH */
|
/* ALTER TEXT SEARCH */
|
||||||
else if (Matches("ALTER", "TEXT", "SEARCH"))
|
else if (Matches("ALTER", "TEXT", "SEARCH"))
|
||||||
|
@ -40,6 +40,7 @@ typedef struct TableSpaceOpts
|
|||||||
float8 random_page_cost;
|
float8 random_page_cost;
|
||||||
float8 seq_page_cost;
|
float8 seq_page_cost;
|
||||||
int effective_io_concurrency;
|
int effective_io_concurrency;
|
||||||
|
int maintenance_io_concurrency;
|
||||||
} TableSpaceOpts;
|
} TableSpaceOpts;
|
||||||
|
|
||||||
extern Oid CreateTableSpace(CreateTableSpaceStmt *stmt);
|
extern Oid CreateTableSpace(CreateTableSpaceStmt *stmt);
|
||||||
|
@ -58,6 +58,7 @@ extern int bgwriter_lru_maxpages;
|
|||||||
extern double bgwriter_lru_multiplier;
|
extern double bgwriter_lru_multiplier;
|
||||||
extern bool track_io_timing;
|
extern bool track_io_timing;
|
||||||
extern int effective_io_concurrency;
|
extern int effective_io_concurrency;
|
||||||
|
extern int maintenance_io_concurrency;
|
||||||
|
|
||||||
extern int checkpoint_flush_after;
|
extern int checkpoint_flush_after;
|
||||||
extern int backend_flush_after;
|
extern int backend_flush_after;
|
||||||
|
@ -16,5 +16,6 @@
|
|||||||
void get_tablespace_page_costs(Oid spcid, float8 *spc_random_page_cost,
|
void get_tablespace_page_costs(Oid spcid, float8 *spc_random_page_cost,
|
||||||
float8 *spc_seq_page_cost);
|
float8 *spc_seq_page_cost);
|
||||||
int get_tablespace_io_concurrency(Oid spcid);
|
int get_tablespace_io_concurrency(Oid spcid);
|
||||||
|
int get_tablespace_maintenance_io_concurrency(Oid spcid);
|
||||||
|
|
||||||
#endif /* SPCCACHE_H */
|
#endif /* SPCCACHE_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user