diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml
index 3b19ea71315..92db00f52d4 100644
--- a/doc/src/sgml/ref/alter_table.sgml
+++ b/doc/src/sgml/ref/alter_table.sgml
@@ -629,7 +629,7 @@ ALTER TABLE [ IF EXISTS ] name
SHARE UPDATE EXCLUSIVE lock will be taken for
- fillfactor and autovacuum storage parameters, as well as the
+ fillfactor, toast and autovacuum storage parameters, as well as the
following planner related parameters:
effective_io_concurrency, parallel_workers, seq_page_cost,
random_page_cost, n_distinct and n_distinct_inherited.
diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index bbb3a51deff..83eef7f10d9 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -1200,6 +1200,27 @@ WITH ( MODULUS numeric_literal, REM
+
+ toast_tuple_target> (integer>)
+
+
+ The toast_tuple_target specifies the minimum tuple length required before
+ we try to move long column values into TOAST tables, and is also the
+ target length we try to reduce the length below once toasting begins.
+ This only affects columns marked as either External or Extended
+ and applies only to new tuples - there is no effect on existing rows.
+ By default this parameter is set to allow at least 4 tuples per block,
+ which with the default blocksize will be 2040 bytes. Valid values are
+ between 128 bytes and the (blocksize - header), by default 8160 bytes.
+ Changing this value may not be useful for very short or very long rows.
+ Note that the default setting is often close to optimal, and
+ it is possible that setting this parameter could have negative
+ effects in some cases.
+ This parameter cannot be set for TOAST tables.
+
+
+
+
parallel_workers (integer)
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 3d0ce9af6f6..aa9c0f1bb94 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -23,6 +23,7 @@
#include "access/nbtree.h"
#include "access/reloptions.h"
#include "access/spgist.h"
+#include "access/tuptoaster.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "commands/tablespace.h"
@@ -290,6 +291,15 @@ static relopt_int intRelOpts[] =
},
-1, -1, INT_MAX
},
+ {
+ {
+ "toast_tuple_target",
+ "Sets the target tuple length at which external columns will be toasted",
+ RELOPT_KIND_HEAP,
+ ShareUpdateExclusiveLock
+ },
+ TOAST_TUPLE_TARGET, 128, TOAST_TUPLE_TARGET_MAIN
+ },
{
{
"pages_per_range",
@@ -1344,6 +1354,8 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, multixact_freeze_table_age)},
{"log_autovacuum_min_duration", RELOPT_TYPE_INT,
offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, log_min_duration)},
+ {"toast_tuple_target", RELOPT_TYPE_INT,
+ offsetof(StdRdOptions, toast_tuple_target)},
{"autovacuum_vacuum_scale_factor", RELOPT_TYPE_REAL,
offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_scale_factor)},
{"autovacuum_analyze_scale_factor", RELOPT_TYPE_REAL,
diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c
index 5a8f1dab83b..c74945a52a5 100644
--- a/src/backend/access/heap/tuptoaster.c
+++ b/src/backend/access/heap/tuptoaster.c
@@ -727,7 +727,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
hoff += sizeof(Oid);
hoff = MAXALIGN(hoff);
/* now convert to a limit on the tuple data size */
- maxDataLen = TOAST_TUPLE_TARGET - hoff;
+ maxDataLen = RelationGetToastTupleTarget(rel, TOAST_TUPLE_TARGET) - hoff;
/*
* Look for attributes with attstorage 'x' to compress. Also find large
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index 4bc61e53806..68fd6fbd54e 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -277,6 +277,7 @@ typedef struct StdRdOptions
{
int32 vl_len_; /* varlena header (do not touch directly!) */
int fillfactor; /* page fill factor in percent (0..100) */
+ int toast_tuple_target; /* target for tuple toasting */
AutoVacOpts autovacuum; /* autovacuum-related options */
bool user_catalog_table; /* use as an additional catalog relation */
int parallel_workers; /* max number of parallel workers */
@@ -285,6 +286,14 @@ typedef struct StdRdOptions
#define HEAP_MIN_FILLFACTOR 10
#define HEAP_DEFAULT_FILLFACTOR 100
+/*
+ * RelationGetToastTupleTarget
+ * Returns the relation's toast_tuple_target. Note multiple eval of argument!
+ */
+#define RelationGetToastTupleTarget(relation, defaulttarg) \
+ ((relation)->rd_options ? \
+ ((StdRdOptions *) (relation)->rd_options)->toast_tuple_target : (defaulttarg))
+
/*
* RelationGetFillFactor
* Returns the relation's fillfactor. Note multiple eval of argument!
diff --git a/src/test/regress/expected/strings.out b/src/test/regress/expected/strings.out
index 35cadb24aa1..3a42ef77be3 100644
--- a/src/test/regress/expected/strings.out
+++ b/src/test/regress/expected/strings.out
@@ -1166,6 +1166,53 @@ SELECT substr(f1, 99995, 10) from toasttest;
567890
(4 rows)
+TRUNCATE TABLE toasttest;
+INSERT INTO toasttest values (repeat('1234567890',400));
+INSERT INTO toasttest values (repeat('1234567890',400));
+INSERT INTO toasttest values (repeat('1234567890',400));
+INSERT INTO toasttest values (repeat('1234567890',400));
+SELECT pg_relation_size('toasttest')/current_setting('block_size')::integer as blocks;
+ blocks
+--------
+ 1
+(1 row)
+
+select pg_relation_size('pg_toast.pg_toast_'||(select oid from pg_class where relname = 'toasttest'))/current_setting('block_size')::integer as blocks;
+ blocks
+--------
+ 3
+(1 row)
+
+SELECT pg_total_relation_size('toasttest')/current_setting('block_size')::integer as blocks;
+ blocks
+--------
+ 9
+(1 row)
+
+TRUNCATE TABLE toasttest;
+ALTER TABLE toasttest set (toast_tuple_target = 4080);
+INSERT INTO toasttest values (repeat('1234567890',400));
+INSERT INTO toasttest values (repeat('1234567890',400));
+INSERT INTO toasttest values (repeat('1234567890',400));
+INSERT INTO toasttest values (repeat('1234567890',400));
+SELECT pg_relation_size('toasttest')/current_setting('block_size')::integer as blocks;
+ blocks
+--------
+ 2
+(1 row)
+
+select pg_relation_size('pg_toast.pg_toast_'||(select oid from pg_class where relname = 'toasttest'))/current_setting('block_size')::integer as blocks;
+ blocks
+--------
+ 0
+(1 row)
+
+SELECT pg_total_relation_size('toasttest')/current_setting('block_size')::integer as blocks;
+ blocks
+--------
+ 6
+(1 row)
+
DROP TABLE toasttest;
--
-- test substr with toasted bytea values
diff --git a/src/test/regress/sql/strings.sql b/src/test/regress/sql/strings.sql
index f9cfaeb44ac..6396693f279 100644
--- a/src/test/regress/sql/strings.sql
+++ b/src/test/regress/sql/strings.sql
@@ -366,6 +366,25 @@ SELECT substr(f1, 99995) from toasttest;
-- string length
SELECT substr(f1, 99995, 10) from toasttest;
+TRUNCATE TABLE toasttest;
+INSERT INTO toasttest values (repeat('1234567890',400));
+INSERT INTO toasttest values (repeat('1234567890',400));
+INSERT INTO toasttest values (repeat('1234567890',400));
+INSERT INTO toasttest values (repeat('1234567890',400));
+SELECT pg_relation_size('toasttest')/current_setting('block_size')::integer as blocks;
+select pg_relation_size('pg_toast.pg_toast_'||(select oid from pg_class where relname = 'toasttest'))/current_setting('block_size')::integer as blocks;
+SELECT pg_total_relation_size('toasttest')/current_setting('block_size')::integer as blocks;
+
+TRUNCATE TABLE toasttest;
+ALTER TABLE toasttest set (toast_tuple_target = 4080);
+INSERT INTO toasttest values (repeat('1234567890',400));
+INSERT INTO toasttest values (repeat('1234567890',400));
+INSERT INTO toasttest values (repeat('1234567890',400));
+INSERT INTO toasttest values (repeat('1234567890',400));
+SELECT pg_relation_size('toasttest')/current_setting('block_size')::integer as blocks;
+select pg_relation_size('pg_toast.pg_toast_'||(select oid from pg_class where relname = 'toasttest'))/current_setting('block_size')::integer as blocks;
+SELECT pg_total_relation_size('toasttest')/current_setting('block_size')::integer as blocks;
+
DROP TABLE toasttest;
--