v14-0004-ALTER-TABLESPACE-.-SET-io_combine_limit.patch
text/x-patch
Filename: v14-0004-ALTER-TABLESPACE-.-SET-io_combine_limit.patch
Type: text/x-patch
Part: 3
Patch
Format: format-patch
Series: patch v14-0004
Subject: ALTER TABLESPACE ... SET (io_combine_limit = ...).
| File | + | − |
|---|---|---|
| doc/src/sgml/ref/alter_tablespace.sgml | 5 | 4 |
| src/backend/access/common/reloptions.c | 11 | 1 |
| src/backend/storage/aio/read_stream.c | 24 | 15 |
| src/backend/utils/cache/spccache.c | 14 | 0 |
| src/bin/psql/tab-complete.c | 2 | 1 |
| src/include/commands/tablespace.h | 1 | 0 |
| src/include/utils/spccache.h | 1 | 0 |
From 163c2ec677c0f57206c53f57c6ac9aff93905246 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Sat, 30 Mar 2024 19:09:44 +1300
Subject: [PATCH v14 4/7] ALTER TABLESPACE ... SET (io_combine_limit = ...).
This is the per-tablespace version of the GUC of the same name.
XXX reloptions.c lacks the ability to accept units eg '64kB'! Which is
why I haven't included it with the main feature commit.
Suggested-by: Tomas Vondra <tomas.vondra@enterprisedb.com
Discussion: https://postgr.es/m/f603ac51-a7ff-496a-99c1-76673635692e%40enterprisedb.com
---
doc/src/sgml/ref/alter_tablespace.sgml | 9 +++---
src/backend/access/common/reloptions.c | 12 +++++++-
src/backend/storage/aio/read_stream.c | 39 ++++++++++++++++----------
src/backend/utils/cache/spccache.c | 14 +++++++++
src/bin/psql/tab-complete.c | 3 +-
src/include/commands/tablespace.h | 1 +
src/include/utils/spccache.h | 1 +
7 files changed, 58 insertions(+), 21 deletions(-)
diff --git a/doc/src/sgml/ref/alter_tablespace.sgml b/doc/src/sgml/ref/alter_tablespace.sgml
index 6ec863400d1..faf0c6e7fbc 100644
--- a/doc/src/sgml/ref/alter_tablespace.sgml
+++ b/doc/src/sgml/ref/alter_tablespace.sgml
@@ -84,16 +84,17 @@ 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>, <varname>effective_io_concurrency</varname>
- and <varname>maintenance_io_concurrency</varname>.
+ <varname>random_page_cost</varname>, <varname>effective_io_concurrency</varname>,
+ <varname>maintenance_io_concurrency</varname> and <varname>io_combine_limit</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, and the executor's prefetching behavior, as established
+ that tablespace, and the executor's prefetching and I/O sizing 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"/>,
- <xref linkend="guc-maintenance-io-concurrency"/>). This may be useful if
+ <xref linkend="guc-maintenance-io-concurrency"/>),
+ <xref linkend="guc-io-combine-limit"/>). 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>
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 963995388bb..573bf1e8606 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -372,6 +372,15 @@ static relopt_int intRelOpts[] =
0, 0, 0
#endif
},
+ {
+ {
+ "io_combine_limit",
+ "Limit on the size of data reads and writes.",
+ RELOPT_KIND_TABLESPACE,
+ ShareUpdateExclusiveLock
+ },
+ -1, 1, MAX_IO_COMBINE_LIMIT
+ },
{
{
"parallel_workers",
@@ -2091,7 +2100,8 @@ tablespace_reloptions(Datum reloptions, bool validate)
{"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)},
- {"maintenance_io_concurrency", RELOPT_TYPE_INT, offsetof(TableSpaceOpts, maintenance_io_concurrency)}
+ {"maintenance_io_concurrency", RELOPT_TYPE_INT, offsetof(TableSpaceOpts, maintenance_io_concurrency)},
+ {"io_combine_limit", RELOPT_TYPE_INT, offsetof(TableSpaceOpts, io_combine_limit)},
};
return (bytea *) build_reloptions(reloptions, validate,
diff --git a/src/backend/storage/aio/read_stream.c b/src/backend/storage/aio/read_stream.c
index f7e9dc1138b..8dd19ed3390 100644
--- a/src/backend/storage/aio/read_stream.c
+++ b/src/backend/storage/aio/read_stream.c
@@ -114,6 +114,7 @@ struct ReadStream
int16 max_pinned_buffers;
int16 pinned_buffers;
int16 distance;
+ int16 io_combine_limit;
bool advice_enabled;
/*
@@ -241,7 +242,7 @@ read_stream_start_pending_read(ReadStream *stream, bool suppress_advice)
/* This should only be called with a pending read. */
Assert(stream->pending_read_nblocks > 0);
- Assert(stream->pending_read_nblocks <= io_combine_limit);
+ Assert(stream->pending_read_nblocks <= stream->io_combine_limit);
/* We had better not exceed the pin limit by starting this read. */
Assert(stream->pinned_buffers + stream->pending_read_nblocks <=
@@ -329,7 +330,7 @@ read_stream_look_ahead(ReadStream *stream, bool suppress_advice)
int16 buffer_index;
void *per_buffer_data;
- if (stream->pending_read_nblocks == io_combine_limit)
+ if (stream->pending_read_nblocks == stream->io_combine_limit)
{
read_stream_start_pending_read(stream, suppress_advice);
suppress_advice = false;
@@ -389,7 +390,7 @@ read_stream_look_ahead(ReadStream *stream, bool suppress_advice)
* signaled end-of-stream, we start the read immediately.
*/
if (stream->pending_read_nblocks > 0 &&
- (stream->pending_read_nblocks == io_combine_limit ||
+ (stream->pending_read_nblocks == stream->io_combine_limit ||
(stream->pending_read_nblocks == stream->distance &&
stream->pinned_buffers == 0) ||
stream->distance == 0) &&
@@ -419,6 +420,7 @@ read_stream_begin_relation(int flags,
size_t size;
int16 queue_size;
int16 max_ios;
+ int16 my_io_combine_limit;
uint32 max_pinned_buffers;
Oid tablespace_id;
@@ -441,15 +443,21 @@ read_stream_begin_relation(int flags,
IsCatalogRelationOid(bmr.smgr->smgr_rlocator.locator.relNumber))
{
/*
- * Avoid circularity while trying to look up tablespace settings or
- * before spccache.c is ready.
+ * Avoid circularity while trying to look up tablespace catalog itself
+ * or before spccache.c is ready: just use the plain GUC values in
+ * those cases.
*/
max_ios = effective_io_concurrency;
+ my_io_combine_limit = io_combine_limit;
}
- else if (flags & READ_STREAM_MAINTENANCE)
- max_ios = get_tablespace_maintenance_io_concurrency(tablespace_id);
else
- max_ios = get_tablespace_io_concurrency(tablespace_id);
+ {
+ if (flags & READ_STREAM_MAINTENANCE)
+ max_ios = get_tablespace_maintenance_io_concurrency(tablespace_id);
+ else
+ max_ios = get_tablespace_io_concurrency(tablespace_id);
+ my_io_combine_limit = get_tablespace_io_combine_limit(tablespace_id);
+ }
max_ios = Min(max_ios, PG_INT16_MAX);
/*
@@ -460,9 +468,9 @@ read_stream_begin_relation(int flags,
* overflow (even though that's not possible with the current GUC range
* limits), allowing also for the spare entry and the overflow space.
*/
- max_pinned_buffers = Max(max_ios * 4, io_combine_limit);
+ max_pinned_buffers = Max(max_ios * 4, my_io_combine_limit);
max_pinned_buffers = Min(max_pinned_buffers,
- PG_INT16_MAX - io_combine_limit - 1);
+ PG_INT16_MAX - my_io_combine_limit - 1);
/* Don't allow this backend to pin more than its share of buffers. */
if (SmgrIsTemp(bmr.smgr))
@@ -488,14 +496,14 @@ read_stream_begin_relation(int flags,
* io_combine_limit - 1 elements.
*/
size = offsetof(ReadStream, buffers);
- size += sizeof(Buffer) * (queue_size + io_combine_limit - 1);
+ size += sizeof(Buffer) * (queue_size + my_io_combine_limit - 1);
size += sizeof(InProgressIO) * Max(1, max_ios);
size += per_buffer_data_size * queue_size;
size += MAXIMUM_ALIGNOF * 2;
stream = (ReadStream *) palloc(size);
memset(stream, 0, offsetof(ReadStream, buffers));
stream->ios = (InProgressIO *)
- MAXALIGN(&stream->buffers[queue_size + io_combine_limit - 1]);
+ MAXALIGN(&stream->buffers[queue_size + my_io_combine_limit - 1]);
if (per_buffer_data_size > 0)
stream->per_buffer_data = (void *)
MAXALIGN(&stream->ios[Max(1, max_ios)]);
@@ -523,6 +531,7 @@ read_stream_begin_relation(int flags,
max_ios = 1;
stream->max_ios = max_ios;
+ stream->io_combine_limit = my_io_combine_limit;
stream->per_buffer_data_size = per_buffer_data_size;
stream->max_pinned_buffers = max_pinned_buffers;
stream->queue_size = queue_size;
@@ -535,7 +544,7 @@ read_stream_begin_relation(int flags,
* doing full io_combine_limit sized reads (behavior B).
*/
if (flags & READ_STREAM_FULL)
- stream->distance = Min(max_pinned_buffers, io_combine_limit);
+ stream->distance = Min(max_pinned_buffers, my_io_combine_limit);
else
stream->distance = 1;
@@ -720,14 +729,14 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
else
{
/* No advice; move towards io_combine_limit (behavior B). */
- if (stream->distance > io_combine_limit)
+ if (stream->distance > stream->io_combine_limit)
{
stream->distance--;
}
else
{
distance = stream->distance * 2;
- distance = Min(distance, io_combine_limit);
+ distance = Min(distance, stream->io_combine_limit);
distance = Min(distance, stream->max_pinned_buffers);
stream->distance = distance;
}
diff --git a/src/backend/utils/cache/spccache.c b/src/backend/utils/cache/spccache.c
index ec63cdc8e52..97664824a4d 100644
--- a/src/backend/utils/cache/spccache.c
+++ b/src/backend/utils/cache/spccache.c
@@ -235,3 +235,17 @@ get_tablespace_maintenance_io_concurrency(Oid spcid)
else
return spc->opts->maintenance_io_concurrency;
}
+
+/*
+ * get_tablespace_io_combine_limit
+ */
+int
+get_tablespace_io_combine_limit(Oid spcid)
+{
+ TableSpaceCacheEntry *spc = get_tablespace(spcid);
+
+ if (!spc->opts || spc->opts->io_combine_limit < 0)
+ return io_combine_limit;
+ else
+ return spc->opts->io_combine_limit;
+}
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index fc6865fc703..a4c746cf63a 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -2633,7 +2633,8 @@ 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", "maintenance_io_concurrency");
+ "effective_io_concurrency", "maintenance_io_concurrency",
+ "io_combine_limit");
/* ALTER TEXT SEARCH */
else if (Matches("ALTER", "TEXT", "SEARCH"))
diff --git a/src/include/commands/tablespace.h b/src/include/commands/tablespace.h
index b6cec632db9..c187283a6dd 100644
--- a/src/include/commands/tablespace.h
+++ b/src/include/commands/tablespace.h
@@ -43,6 +43,7 @@ typedef struct TableSpaceOpts
float8 seq_page_cost;
int effective_io_concurrency;
int maintenance_io_concurrency;
+ int io_combine_limit;
} TableSpaceOpts;
extern Oid CreateTableSpace(CreateTableSpaceStmt *stmt);
diff --git a/src/include/utils/spccache.h b/src/include/utils/spccache.h
index 11cfa719955..f8a19764a8f 100644
--- a/src/include/utils/spccache.h
+++ b/src/include/utils/spccache.h
@@ -17,5 +17,6 @@ extern void get_tablespace_page_costs(Oid spcid, float8 *spc_random_page_cost,
float8 *spc_seq_page_cost);
extern int get_tablespace_io_concurrency(Oid spcid);
extern int get_tablespace_maintenance_io_concurrency(Oid spcid);
+extern int get_tablespace_io_combine_limit(Oid spcid);
#endif /* SPCCACHE_H */
--
2.44.0