Commit c2513365 authored by Simon Riggs's avatar Simon Riggs

Parameter toast_tuple_target controls TOAST for new rows

Specifies the point at which we try to move long column values
into TOAST tables.

No effect on existing rows.

Discussion: https://postgr.es/m/CANP8+jKsVmw6CX6YP9z7zqkTzcKV1+Uzr3XjKcZW=2Ya00OyQQ@mail.gmail.com

Author: Simon Riggs <simon@2ndQudrant.com>
Reviewed-by: default avatarAndrew Dunstan <andrew.dunstan@2ndQuadrant.com>
parent 52f63bd9
......@@ -629,7 +629,7 @@ ALTER TABLE [ IF EXISTS ] <replaceable class="parameter">name</replaceable>
<para>
<literal>SHARE UPDATE EXCLUSIVE</literal> 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:
<varname>effective_io_concurrency</varname>, <varname>parallel_workers</varname>, <varname>seq_page_cost</varname>,
<varname>random_page_cost</varname>, <varname>n_distinct</varname> and <varname>n_distinct_inherited</varname>.
......
......@@ -1200,6 +1200,27 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
</listitem>
</varlistentry>
<varlistentry>
<term><literal>toast_tuple_target</> (<type>integer</>)</term>
<listitem>
<para>
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.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>parallel_workers</literal> (<type>integer</type>)</term>
<listitem>
......
......@@ -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,
......
......@@ -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
......
......@@ -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!
......
......@@ -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
......
......@@ -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;
--
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment