1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-09 22:41:56 +03:00

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 558a9165e0.  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:
Thomas Munro
2020-03-16 12:31:34 +13:00
parent b09ff53667
commit fc34b0d9de
12 changed files with 109 additions and 23 deletions

View File

@ -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,

View File

@ -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);

View File

@ -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.

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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"))

View File

@ -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);

View File

@ -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;

View File

@ -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 */