From ca7c8168de76459380577eda56a3ed09b4f6195c Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Wed, 22 Jul 2009 01:21:22 +0000 Subject: [PATCH] Tweak TOAST code so that columns marked with MAIN storage strategy are not forced out-of-line unless that is necessary to make the row fit on a page. Previously, they were forced out-of-line if needed to get the row down to the default target size (1/4th page). Kevin Grittner --- doc/src/sgml/storage.sgml | 4 +-- src/backend/access/heap/tuptoaster.c | 8 ++++-- src/include/access/tuptoaster.h | 39 ++++++++++++++++++---------- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/doc/src/sgml/storage.sgml b/doc/src/sgml/storage.sgml index ee7f814ea89..fcdbd0ee36f 100644 --- a/doc/src/sgml/storage.sgml +++ b/doc/src/sgml/storage.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/storage.sgml,v 1.29 2009/06/17 21:58:49 tgl Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/storage.sgml,v 1.30 2009/07/22 01:21:22 tgl Exp $ --> <chapter id="storage"> @@ -347,7 +347,7 @@ The <acronym>TOAST</> code recognizes four different strategies for storing <literal>MAIN</literal> allows compression but not out-of-line storage. (Actually, out-of-line storage will still be performed for such columns, but only as a last resort when there is no other - way to make the row small enough.) + way to make the row small enough to fit on a page.) </para> </listitem> </itemizedlist> diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c index a3203085b7a..781bfd2e486 100644 --- a/src/backend/access/heap/tuptoaster.c +++ b/src/backend/access/heap/tuptoaster.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.93 2009/06/11 14:48:54 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.94 2009/07/22 01:21:22 tgl Exp $ * * * INTERFACE ROUTINES @@ -796,8 +796,12 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, } /* - * Finally we store attributes of type 'm' external, if possible. + * Finally we store attributes of type 'm' externally. At this point + * we increase the target tuple size, so that 'm' attributes aren't + * stored externally unless really necessary. */ + maxDataLen = TOAST_TUPLE_TARGET_MAIN - hoff; + while (heap_compute_data_size(tupleDesc, toast_values, toast_isnull) > maxDataLen && rel->rd_rel->reltoastrelid != InvalidOid) diff --git a/src/include/access/tuptoaster.h b/src/include/access/tuptoaster.h index db2f7e57607..f8dd7f82f5b 100644 --- a/src/include/access/tuptoaster.h +++ b/src/include/access/tuptoaster.h @@ -6,7 +6,7 @@ * * Copyright (c) 2000-2009, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/include/access/tuptoaster.h,v 1.43 2009/01/01 17:23:56 momjian Exp $ + * $PostgreSQL: pgsql/src/include/access/tuptoaster.h,v 1.44 2009/07/22 01:21:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -24,20 +24,26 @@ #define TOAST_INDEX_HACK +/* + * Find the maximum size of a tuple if there are to be N tuples per page. + */ +#define MaximumBytesPerTuple(tuplesPerPage) \ + MAXALIGN_DOWN((BLCKSZ - \ + MAXALIGN(SizeOfPageHeaderData + (tuplesPerPage) * sizeof(ItemIdData))) \ + / (tuplesPerPage)) + /* * These symbols control toaster activation. If a tuple is larger than * TOAST_TUPLE_THRESHOLD, we will try to toast it down to no more than - * TOAST_TUPLE_TARGET bytes. Both numbers include all tuple header overhead - * and between-fields alignment padding, but we do *not* consider any - * end-of-tuple alignment padding; hence the values can be compared directly - * to a tuple's t_len field. + * TOAST_TUPLE_TARGET bytes through compressing compressible fields and + * moving EXTENDED and EXTERNAL data out-of-line. * * The numbers need not be the same, though they currently are. It doesn't * make sense for TARGET to exceed THRESHOLD, but it could be useful to make * it be smaller. * * Currently we choose both values to match the largest tuple size for which - * TOAST_TUPLES_PER_PAGE tuples can fit on a disk page. + * TOAST_TUPLES_PER_PAGE tuples can fit on a heap page. * * XXX while these can be modified without initdb, some thought needs to be * given to needs_toast_table() in toasting.c before unleashing random @@ -46,13 +52,21 @@ */ #define TOAST_TUPLES_PER_PAGE 4 -#define TOAST_TUPLE_THRESHOLD \ - MAXALIGN_DOWN((BLCKSZ - \ - MAXALIGN(SizeOfPageHeaderData + TOAST_TUPLES_PER_PAGE * sizeof(ItemIdData))) \ - / TOAST_TUPLES_PER_PAGE) +#define TOAST_TUPLE_THRESHOLD MaximumBytesPerTuple(TOAST_TUPLES_PER_PAGE) #define TOAST_TUPLE_TARGET TOAST_TUPLE_THRESHOLD +/* + * The code will also consider moving MAIN data out-of-line, but only as a + * last resort if the previous steps haven't reached the target tuple size. + * In this phase we use a different target size, currently equal to the + * largest tuple that will fit on a heap page. This is reasonable since + * the user has told us to keep the data in-line if at all possible. + */ +#define TOAST_TUPLES_PER_PAGE_MAIN 1 + +#define TOAST_TUPLE_TARGET_MAIN MaximumBytesPerTuple(TOAST_TUPLES_PER_PAGE_MAIN) + /* * If an index value is larger than TOAST_INDEX_TARGET, we will try to * compress it (we can't move it out-of-line, however). Note that this @@ -72,10 +86,7 @@ */ #define EXTERN_TUPLES_PER_PAGE 4 /* tweak only this */ -#define EXTERN_TUPLE_MAX_SIZE \ - MAXALIGN_DOWN((BLCKSZ - \ - MAXALIGN(SizeOfPageHeaderData + EXTERN_TUPLES_PER_PAGE * sizeof(ItemIdData))) \ - / EXTERN_TUPLES_PER_PAGE) +#define EXTERN_TUPLE_MAX_SIZE MaximumBytesPerTuple(EXTERN_TUPLES_PER_PAGE) #define TOAST_MAX_CHUNK_SIZE \ (EXTERN_TUPLE_MAX_SIZE - \ -- GitLab