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: Andrew Dunstan <andrew.dunstan@2ndQuadrant.com>
This commit is contained in:
Simon Riggs 2017-11-20 09:50:10 +11:00
parent 52f63bd916
commit c2513365a0
7 changed files with 110 additions and 2 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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