Commit 23c4978e authored by Tom Lane's avatar Tom Lane

Rename MaxTupleSize to MaxHeapTupleSize to clarify that it's not meant to

describe the maximum size of index tuples (which is typically AM-dependent
anyway); and consequently remove the bogus deduction for "special space"
that was built into it.

Adjust TOAST_TUPLE_THRESHOLD and TOAST_MAX_CHUNK_SIZE to avoid wasting two
bytes per toast chunk, and to ensure that the calculation correctly tracks any
future changes in page header size.  The computation had been inaccurate in a
way that didn't cause any harm except space wastage, but future changes could
have broken it more drastically.

Fix the calculation of BTMaxItemSize, which was formerly computed as 1 byte
more than it could safely be.  This didn't cause any harm in practice because
it's only compared against maxalign'd lengths, but future changes in the size
of page headers or btree special space could have exposed the problem.

initdb forced because of change in TOAST_MAX_CHUNK_SIZE, which alters the
storage of toast tables.
parent a2e092e1
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.226 2007/02/04 20:00:37 tgl Exp $
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.227 2007/02/05 04:22:18 tgl Exp $
*
*
* INTERFACE ROUTINES
......@@ -3463,7 +3463,7 @@ heap_xlog_insert(XLogRecPtr lsn, XLogRecord *record)
struct
{
HeapTupleHeaderData hdr;
char data[MaxTupleSize];
char data[MaxHeapTupleSize];
} tbuf;
HeapTupleHeader htup;
xl_heap_header xlhdr;
......@@ -3505,7 +3505,7 @@ heap_xlog_insert(XLogRecPtr lsn, XLogRecord *record)
elog(PANIC, "heap_insert_redo: invalid max offset number");
newlen = record->xl_len - SizeOfHeapInsert - SizeOfHeapHeader;
Assert(newlen <= MaxTupleSize);
Assert(newlen <= MaxHeapTupleSize);
memcpy((char *) &xlhdr,
(char *) xlrec + SizeOfHeapInsert,
SizeOfHeapHeader);
......@@ -3551,7 +3551,7 @@ heap_xlog_update(XLogRecPtr lsn, XLogRecord *record, bool move)
struct
{
HeapTupleHeaderData hdr;
char data[MaxTupleSize];
char data[MaxHeapTupleSize];
} tbuf;
xl_heap_header xlhdr;
int hsize;
......@@ -3668,7 +3668,7 @@ newsame:;
hsize += (2 * sizeof(TransactionId));
newlen = record->xl_len - hsize;
Assert(newlen <= MaxTupleSize);
Assert(newlen <= MaxHeapTupleSize);
memcpy((char *) &xlhdr,
(char *) xlrec + SizeOfHeapUpdate,
SizeOfHeapHeader);
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/heap/hio.c,v 1.64 2007/01/05 22:19:22 momjian Exp $
* $PostgreSQL: pgsql/src/backend/access/heap/hio.c,v 1.65 2007/02/05 04:22:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -118,12 +118,12 @@ RelationGetBufferForTuple(Relation relation, Size len,
/*
* If we're gonna fail for oversize tuple, do it right away
*/
if (len > MaxTupleSize)
if (len > MaxHeapTupleSize)
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("row is too big: size %lu, maximum size %lu",
(unsigned long) len,
(unsigned long) MaxTupleSize)));
(unsigned long) MaxHeapTupleSize)));
/* Compute desired extra freespace due to fillfactor option */
saveFreeSpace = RelationGetTargetPageFreeSpace(relation,
......@@ -147,7 +147,7 @@ RelationGetBufferForTuple(Relation relation, Size len,
* When use_fsm is false, we either put the tuple onto the existing target
* page or extend the relation.
*/
if (len + saveFreeSpace <= MaxTupleSize)
if (len + saveFreeSpace <= MaxHeapTupleSize)
targetBlock = relation->rd_targblock;
else
{
......
......@@ -13,7 +13,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.344 2007/02/01 19:10:26 momjian Exp $
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.345 2007/02/05 04:22:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1236,7 +1236,7 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
nunused;
double free_space,
usable_free_space;
Size min_tlen = MaxTupleSize;
Size min_tlen = MaxHeapTupleSize;
Size max_tlen = 0;
bool do_shrinking = true;
VTupleLink vtlinks = (VTupleLink) palloc(100 * sizeof(VTupleLinkData));
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/access/htup.h,v 1.89 2007/01/09 22:01:00 momjian Exp $
* $PostgreSQL: pgsql/src/include/access/htup.h,v 1.90 2007/02/05 04:22:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -314,19 +314,17 @@ do { \
#define BITMAPLEN(NATTS) (((int)(NATTS) + 7) / 8)
/*
* MaxTupleSize is the maximum allowed size of a tuple, including header and
* MAXALIGN alignment padding. Basically it's BLCKSZ minus the other stuff
* that has to be on a disk page. The "other stuff" includes access-method-
* dependent "special space", which we assume will be no more than
* MaxSpecialSpace bytes (currently, on heap pages it's actually zero).
* MaxHeapTupleSize is the maximum allowed size of a heap tuple, including
* header and MAXALIGN alignment padding. Basically it's BLCKSZ minus the
* other stuff that has to be on a disk page. Since heap pages use no
* "special space", there's no deduction for that.
*
* NOTE: we do not need to count an ItemId for the tuple because
* sizeof(PageHeaderData) includes the first ItemId on the page.
* sizeof(PageHeaderData) includes the first ItemId on the page. But beware
* of assuming that, say, you can fit 2 tuples of size MaxHeapTupleSize/2
* on the same page.
*/
#define MaxSpecialSpace 32
#define MaxTupleSize \
(BLCKSZ - MAXALIGN(sizeof(PageHeaderData) + MaxSpecialSpace))
#define MaxHeapTupleSize (BLCKSZ - MAXALIGN(sizeof(PageHeaderData)))
/*
* MaxHeapTuplesPerPage is an upper bound on the number of tuples that can
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.109 2007/01/20 18:43:35 neilc Exp $
* $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.110 2007/02/05 04:22:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -99,13 +99,18 @@ typedef struct BTMetaPageData
#define BTREE_VERSION 2 /* current version number */
/*
* Maximum size of a btree index entry, including its tuple header.
*
* We actually need to be able to fit three items on every page,
* so restrict any one item to 1/3 the per-page available space.
*
* Note: sizeof(PageHeaderData) includes the first ItemId, but we have
* to allow for 2 more, as well as the end-of-page special space.
*/
#define BTMaxItemSize(page) \
((PageGetPageSize(page) - \
sizeof(PageHeaderData) - \
MAXALIGN(sizeof(BTPageOpaqueData))) / 3 - sizeof(ItemIdData))
MAXALIGN_DOWN((PageGetPageSize(page) - \
MAXALIGN(sizeof(PageHeaderData) + 2*sizeof(ItemIdData)) - \
MAXALIGN(sizeof(BTPageOpaqueData))) / 3)
/*
* The leaf-page fillfactor defaults to 90% but is user-adjustable.
......
......@@ -6,7 +6,7 @@
*
* Copyright (c) 2000-2007, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/include/access/tuptoaster.h,v 1.31 2007/02/04 20:00:37 tgl Exp $
* $PostgreSQL: pgsql/src/include/access/tuptoaster.h,v 1.32 2007/02/05 04:22:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -29,40 +29,47 @@
* 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. (Note that the symbol values are not
* necessarily MAXALIGN multiples.)
* to a tuple's t_len field. We choose TOAST_TUPLE_THRESHOLD with the
* knowledge that toast-table tuples will be exactly that size, and we'd
* like to fit four of them per page with minimal space wastage.
*
* The numbers need not be the same, though they currently are.
*
* Note: sizeof(PageHeaderData) includes the first ItemId, but we have
* to allow for 3 more, if we want to fit 4 tuples on a page.
*/
#define TOAST_TUPLE_THRESHOLD (MaxTupleSize / 4)
#define TOAST_TUPLE_THRESHOLD \
MAXALIGN_DOWN((BLCKSZ - \
MAXALIGN(sizeof(PageHeaderData) + 3 * sizeof(ItemIdData))) \
/ 4)
#define TOAST_TUPLE_TARGET (MaxTupleSize / 4)
#define TOAST_TUPLE_TARGET TOAST_TUPLE_THRESHOLD
/*
* 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
* number is per-datum, not per-tuple, for simplicity in index_form_tuple().
*/
#define TOAST_INDEX_TARGET (MaxTupleSize / 16)
#define TOAST_INDEX_TARGET (MaxHeapTupleSize / 16)
/*
* When we store an oversize datum externally, we divide it into chunks
* containing at most TOAST_MAX_CHUNK_SIZE data bytes. This number *must*
* be small enough that the completed toast-table tuple (including the
* ID and sequence fields and all overhead) is no more than MaxTupleSize
* ID and sequence fields and all overhead) is no more than MaxHeapTupleSize
* bytes. It *should* be small enough to make toast-table tuples no more
* than TOAST_TUPLE_THRESHOLD bytes, else heapam.c will uselessly invoke
* the toaster on toast-table tuples.
* the toaster on toast-table tuples. The current coding ensures that the
* maximum tuple length is exactly TOAST_TUPLE_THRESHOLD bytes.
*
* NB: you cannot change this value without forcing initdb, at least not
* if your DB contains any multi-chunk toasted values.
*/
#define TOAST_MAX_CHUNK_SIZE (TOAST_TUPLE_THRESHOLD - \
MAXALIGN( \
MAXALIGN(offsetof(HeapTupleHeaderData, t_bits)) + \
sizeof(Oid) + \
sizeof(int32) + \
VARHDRSZ))
MAXALIGN(offsetof(HeapTupleHeaderData, t_bits)) - \
sizeof(Oid) - \
sizeof(int32) - \
VARHDRSZ)
/* ----------
......
......@@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/c.h,v 1.217 2007/01/25 03:30:43 momjian Exp $
* $PostgreSQL: pgsql/src/include/c.h,v 1.218 2007/02/05 04:22:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -537,12 +537,12 @@ typedef NameData *Name;
/* ----------------
* Alignment macros: align a length or address appropriately for a given type.
* The fooALIGN() macros round up to a multiple of the required alignment,
* while the fooALIGN_DOWN() macros round down. The latter are more useful
* for problems like "how many X-sized structures will fit in a page?".
*
* There used to be some incredibly crufty platform-dependent hackery here,
* but now we rely on the configure script to get the info for us. Much nicer.
*
* NOTE: TYPEALIGN will not work if ALIGNVAL is not a power of 2.
* That case seems extremely unlikely to occur in practice, however.
* NOTE: TYPEALIGN[_DOWN] will not work if ALIGNVAL is not a power of 2.
* That case seems extremely unlikely to be needed in practice, however.
* ----------------
*/
......@@ -557,6 +557,14 @@ typedef NameData *Name;
/* MAXALIGN covers only built-in types, not buffers */
#define BUFFERALIGN(LEN) TYPEALIGN(ALIGNOF_BUFFER, (LEN))
#define TYPEALIGN_DOWN(ALIGNVAL,LEN) \
(((long) (LEN)) & ~((long) ((ALIGNVAL) - 1)))
#define SHORTALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_SHORT, (LEN))
#define INTALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_INT, (LEN))
#define LONGALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_LONG, (LEN))
#define DOUBLEALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_DOUBLE, (LEN))
#define MAXALIGN_DOWN(LEN) TYPEALIGN_DOWN(MAXIMUM_ALIGNOF, (LEN))
/* ----------------------------------------------------------------
* Section 6: widely useful macros
......
......@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.379 2007/02/03 14:06:55 petere Exp $
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.380 2007/02/05 04:22:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200702031
#define CATALOG_VERSION_NO 200702041
#endif
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