diff options
| author | Tom Lane <tgl@sss.pgh.pa.us> | 2006-06-27 02:51:40 +0000 |
|---|---|---|
| committer | Tom Lane <tgl@sss.pgh.pa.us> | 2006-06-27 02:51:40 +0000 |
| commit | 3f50ba27cf417eb57fd310c2a88f76a6ea6b966e (patch) | |
| tree | e9dec4aaac793ed8efab65488e62532057f91704 /src/include | |
| parent | fe491fb9afd07f3cc9b8aabb17f43049b79258a9 (diff) | |
| download | postgresql-3f50ba27cf417eb57fd310c2a88f76a6ea6b966e.tar.gz | |
Create infrastructure for 'MinimalTuple' representation of in-memory
tuples with less header overhead than a regular HeapTuple, per my
recent proposal. Teach TupleTableSlot code how to deal with these.
As proof of concept, change tuplestore.c to store MinimalTuples instead
of HeapTuples. Future patches will expand the concept to other places
where it is useful.
Diffstat (limited to 'src/include')
| -rw-r--r-- | src/include/access/heapam.h | 10 | ||||
| -rw-r--r-- | src/include/access/htup.h | 71 | ||||
| -rw-r--r-- | src/include/executor/tuptable.h | 25 | ||||
| -rw-r--r-- | src/include/utils/tuplestore.h | 24 |
4 files changed, 112 insertions, 18 deletions
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index e016a52740..7301be4ae3 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.111 2006/05/10 23:18:39 tgl Exp $ + * $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.112 2006/06/27 02:51:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -217,7 +217,13 @@ extern void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull); extern void heap_deformtuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, char *nulls); -extern void heap_freetuple(HeapTuple tuple); +extern void heap_freetuple(HeapTuple htup); +extern MinimalTuple heap_form_minimal_tuple(TupleDesc tupleDescriptor, + Datum *values, bool *isnull); +extern void heap_free_minimal_tuple(MinimalTuple mtup); +extern MinimalTuple heap_copy_minimal_tuple(MinimalTuple mtup); +extern HeapTuple heap_tuple_from_minimal_tuple(MinimalTuple mtup); +extern MinimalTuple minimal_tuple_from_heap_tuple(HeapTuple htup); extern HeapTuple heap_addheader(int natts, bool withoid, Size structlen, void *structure); diff --git a/src/include/access/htup.h b/src/include/access/htup.h index 57db9f8493..170ad657fb 100644 --- a/src/include/access/htup.h +++ b/src/include/access/htup.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/htup.h,v 1.82 2006/05/10 23:18:39 tgl Exp $ + * $PostgreSQL: pgsql/src/include/access/htup.h,v 1.83 2006/06/27 02:51:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -31,7 +31,7 @@ */ #define MaxTupleAttributeNumber 1664 /* 8 * 208 */ -/*---------- +/* * MaxHeapAttributeNumber limits the number of (user) columns in a table. * This should be somewhat less than MaxTupleAttributeNumber. It must be * at least one less, else we will fail to do UPDATEs on a maximal-width @@ -42,11 +42,10 @@ * In any case, depending on column data types you will likely be running * into the disk-block-based limit on overall tuple size if you have more * than a thousand or so columns. TOAST won't help. - *---------- */ #define MaxHeapAttributeNumber 1600 /* 8 * 200 */ -/*---------- +/* * Heap tuple header. To avoid wasting space, the fields should be * layed out in such a way to avoid structure padding. * @@ -101,7 +100,6 @@ * t_infomask), then it is stored just before the user data, which begins at * the offset shown by t_hoff. Note that t_hoff must be a multiple of * MAXALIGN. - *---------- */ typedef struct HeapTupleFields @@ -141,6 +139,8 @@ typedef struct HeapTupleHeaderData ItemPointerData t_ctid; /* current TID of this or newer tuple */ + /* Fields below here must match MinimalTupleData! */ + int16 t_natts; /* number of attributes */ uint16 t_infomask; /* various flag bits, see below */ @@ -355,6 +355,62 @@ do { \ /* + * MinimalTuple is an alternate representation that is used for transient + * tuples inside the executor, in places where transaction status information + * is not required, the tuple rowtype is known, and shaving off a few bytes + * is worthwhile because we need to store many tuples. The representation + * is chosen so that tuple access routines can work with either full or + * minimal tuples via a HeapTupleData pointer structure. The access routines + * see no difference, except that they must not access the transaction status + * or t_ctid fields because those aren't there. + * + * For the most part, MinimalTuples should be accessed via TupleTableSlot + * routines. These routines will prevent access to the "system columns" + * and thereby prevent accidental use of the nonexistent fields. + * + * MinimalTupleData contains a length word, some padding, and fields matching + * HeapTupleHeaderData beginning with t_natts. The padding is chosen so that + * offsetof(t_natts) is the same modulo MAXIMUM_ALIGNOF in both structs. + * This makes data alignment rules equivalent in both cases. + * + * When a minimal tuple is accessed via a HeapTupleData pointer, t_data is + * set to point MINIMAL_TUPLE_OFFSET bytes before the actual start of the + * minimal tuple --- that is, where a full tuple matching the minimal tuple's + * data would start. This trick is what makes the structs seem equivalent. + * + * Note that t_hoff is computed the same as in a full tuple, hence it includes + * the MINIMAL_TUPLE_OFFSET distance. t_len does not include that, however. + */ +#define MINIMAL_TUPLE_OFFSET \ + ((offsetof(HeapTupleHeaderData, t_natts) - sizeof(uint32)) / MAXIMUM_ALIGNOF * MAXIMUM_ALIGNOF) +#define MINIMAL_TUPLE_PADDING \ + ((offsetof(HeapTupleHeaderData, t_natts) - sizeof(uint32)) % MAXIMUM_ALIGNOF) + +typedef struct MinimalTupleData +{ + uint32 t_len; /* actual length of minimal tuple */ + + char mt_padding[MINIMAL_TUPLE_PADDING]; + + /* Fields below here must match HeapTupleHeaderData! */ + + int16 t_natts; /* number of attributes */ + + uint16 t_infomask; /* various flag bits, see below */ + + uint8 t_hoff; /* sizeof header incl. bitmap, padding */ + + /* ^ - 27 bytes - ^ */ + + bits8 t_bits[1]; /* bitmap of NULLs -- VARIABLE LENGTH */ + + /* MORE DATA FOLLOWS AT END OF STRUCT */ +} MinimalTupleData; + +typedef MinimalTupleData *MinimalTuple; + + +/* * HeapTupleData is an in-memory data structure that points to a tuple. * * There are several ways in which this data structure is used: @@ -376,6 +432,11 @@ do { \ * it's difficult to tell apart from case #1. It should be used only in * limited contexts where the code knows that case #1 will never apply.) * + * * Separately allocated minimal tuple: t_data points MINIMAL_TUPLE_OFFSET + * bytes before the start of a MinimalTuple. As with the previous case, + * this can't be told apart from case #1 by inspection; code setting up + * or destroying this representation has to know what it's doing. + * * t_len should always be valid, except in the pointer-to-nothing case. * t_self and t_tableOid should be valid if the HeapTupleData points to * a disk buffer, or if it represents a copy of a tuple on disk. They diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h index b506651fbb..8531835134 100644 --- a/src/include/executor/tuptable.h +++ b/src/include/executor/tuptable.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/tuptable.h,v 1.31 2006/06/16 18:42:23 tgl Exp $ + * $PostgreSQL: pgsql/src/include/executor/tuptable.h,v 1.32 2006/06/27 02:51:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -23,7 +23,8 @@ * independent TupleTableSlots. There are several cases we need to handle: * 1. physical tuple in a disk buffer page * 2. physical tuple constructed in palloc'ed memory - * 3. "virtual" tuple consisting of Datum/isnull arrays + * 3. "minimal" physical tuple constructed in palloc'ed memory + * 4. "virtual" tuple consisting of Datum/isnull arrays * * The first two cases are similar in that they both deal with "materialized" * tuples, but resource management is different. For a tuple in a disk page @@ -31,6 +32,11 @@ * to the tuple is dropped; while for a palloc'd tuple we usually want the * tuple pfree'd when the TupleTableSlot's reference is dropped. * + * A "minimal" tuple is handled similarly to a palloc'd regular tuple. + * At present, minimal tuples never are stored in buffers, so there is no + * parallel to case 1. Note that a minimal tuple has no "system columns". + * (Actually, it could have an OID, but we have no need to access the OID.) + * * A "virtual" tuple is an optimization used to minimize physical data * copying in a nest of plan nodes. Any pass-by-reference Datums in the * tuple point to storage that is not directly associated with the @@ -83,6 +89,15 @@ * tts_values/tts_isnull are allocated when a descriptor is assigned to the * slot; they are of length equal to the descriptor's natts. * + * tts_mintuple must always be NULL if the slot does not hold a "minimal" + * tuple. When it does, tts_mintuple points to the actual MinimalTupleData + * object (the thing to be pfree'd if tts_shouldFree is true). In this case + * tts_tuple points at tts_minhdr and the fields of that are set correctly + * for access to the minimal tuple; in particular, tts_minhdr.t_data points + * MINIMAL_TUPLE_OFFSET bytes before tts_mintuple. (tts_mintuple is therefore + * redundant, but for code simplicity we store it explicitly anyway.) This + * case otherwise behaves identically to the regular-physical-tuple case. + * * tts_slow/tts_off are saved state for slot_deform_tuple, and should not * be touched by any other code. *---------- @@ -100,6 +115,8 @@ typedef struct TupleTableSlot int tts_nvalid; /* # of valid values in tts_values */ Datum *tts_values; /* current per-attribute values */ bool *tts_isnull; /* current per-attribute isnull flags */ + MinimalTuple tts_mintuple; /* set if it's a minimal tuple, else NULL */ + HeapTupleData tts_minhdr; /* workspace if it's a minimal tuple */ long tts_off; /* saved state for slot_deform_tuple */ } TupleTableSlot; @@ -133,10 +150,14 @@ extern TupleTableSlot *ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree); +extern TupleTableSlot *ExecStoreMinimalTuple(MinimalTuple mtup, + TupleTableSlot *slot, + bool shouldFree); extern TupleTableSlot *ExecClearTuple(TupleTableSlot *slot); extern TupleTableSlot *ExecStoreVirtualTuple(TupleTableSlot *slot); extern TupleTableSlot *ExecStoreAllNullTuple(TupleTableSlot *slot); extern HeapTuple ExecCopySlotTuple(TupleTableSlot *slot); +extern MinimalTuple ExecCopySlotMinimalTuple(TupleTableSlot *slot); extern HeapTuple ExecFetchSlotTuple(TupleTableSlot *slot); extern HeapTuple ExecMaterializeSlot(TupleTableSlot *slot); extern TupleTableSlot *ExecCopySlot(TupleTableSlot *dstslot, diff --git a/src/include/utils/tuplestore.h b/src/include/utils/tuplestore.h index a671bf438f..6227934414 100644 --- a/src/include/utils/tuplestore.h +++ b/src/include/utils/tuplestore.h @@ -14,17 +14,23 @@ * A temporary file is used to handle the data if it exceeds the * space limit specified by the caller. * + * Beginning in Postgres 8.2, what is stored is just MinimalTuples; + * callers cannot expect valid system columns in regurgitated tuples. + * Also, we have changed the API to return tuples in TupleTableSlots, + * so that there is a check to prevent attempted access to system columns. + * * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/tuplestore.h,v 1.17 2006/03/05 15:59:08 momjian Exp $ + * $PostgreSQL: pgsql/src/include/utils/tuplestore.h,v 1.18 2006/06/27 02:51:40 tgl Exp $ * *------------------------------------------------------------------------- */ #ifndef TUPLESTORE_H #define TUPLESTORE_H -#include "access/htup.h" +#include "executor/tuptable.h" + /* Tuplestorestate is an opaque type whose details are not known outside * tuplestore.c. @@ -32,7 +38,7 @@ typedef struct Tuplestorestate Tuplestorestate; /* - * Currently we only need to store HeapTuples, but it would be easy + * Currently we only need to store MinimalTuples, but it would be easy * to support the same behavior for IndexTuples and/or bare Datums. */ @@ -40,17 +46,17 @@ extern Tuplestorestate *tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes); -extern void tuplestore_puttuple(Tuplestorestate *state, void *tuple); +extern void tuplestore_puttupleslot(Tuplestorestate *state, + TupleTableSlot *slot); +extern void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple); /* tuplestore_donestoring() used to be required, but is no longer used */ #define tuplestore_donestoring(state) ((void) 0) /* backwards scan is only allowed if randomAccess was specified 'true' */ -extern void *tuplestore_gettuple(Tuplestorestate *state, bool forward, - bool *should_free); - -#define tuplestore_getheaptuple(state, forward, should_free) \ - ((HeapTuple) tuplestore_gettuple(state, forward, should_free)) +extern bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, + TupleTableSlot *slot); +extern bool tuplestore_advance(Tuplestorestate *state, bool forward); extern void tuplestore_end(Tuplestorestate *state); |
