]> granicus.if.org Git - postgresql/commitdiff
Parameter toast_tuple_target controls TOAST for new rows
authorSimon Riggs <simon@2ndQuadrant.com>
Sun, 19 Nov 2017 22:50:10 +0000 (09:50 +1100)
committerSimon Riggs <simon@2ndQuadrant.com>
Sun, 19 Nov 2017 22:50:10 +0000 (09:50 +1100)
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>
doc/src/sgml/ref/alter_table.sgml
doc/src/sgml/ref/create_table.sgml
src/backend/access/common/reloptions.c
src/backend/access/heap/tuptoaster.c
src/include/utils/rel.h
src/test/regress/expected/strings.out
src/test/regress/sql/strings.sql

index 3b19ea71315d6697fc32acbd9416f776cd0a295c..92db00f52d483a5e6240d35400c220ea5d8c3d8f 100644 (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>.
index bbb3a51deff202bfa296d468846b55ff79a14eba..83eef7f10d9cb979e0b70ae195c0176c9137aa14 100644 (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>
index 3d0ce9af6f618dce97bdada08225f95a20d065bf..aa9c0f1bb94e87fd5d68b26dc8132644ed2b511f 100644 (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,
index 5a8f1dab83b60642dc915a1850578af4dbf4ade8..c74945a52a5a7b36699a4d42001a592d350d4e0a 100644 (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
index 4bc61e53806b50c9f7d5f0efef7ef95daf3bbdbc..68fd6fbd54e6ed0492fd429440717a976d505524 100644 (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!
index 35cadb24aa1f61d91185d0bc9a0eda2ac59d8d4b..3a42ef77be3ee1e5303fcb1828427158971def53 100644 (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
index f9cfaeb44ac2f55d8f5c859a0951aaba9e1dd381..6396693f2796713cf4c29ae2f0684f2051990052 100644 (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;
 
 --