tuples-per-page.patch
text/x-patch
Filename: tuples-per-page.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| doc/src/sgml/ref/create_table.sgml | 21 | 0 |
| src/backend/access/common/reloptions.c | 9 | 0 |
| src/backend/access/heap/heapam.c | 2 | 2 |
| src/backend/access/heap/rewriteheap.c | 1 | 1 |
| src/backend/access/heap/tuptoaster.c | 7 | 1 |
| src/backend/catalog/toasting.c | 1 | 1 |
| src/include/access/tuptoaster.h | 2 | 2 |
| src/include/utils/rel.h | 8 | 0 |
diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index 52b2dc8..ba36923 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -848,6 +848,27 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE [ IF NOT EXISTS ] <repl
</varlistentry>
<varlistentry>
+ <term><literal>tuples_per_page</> (<type>integer</>)</term>
+ <listitem>
+ <para>
+ The tuples_per_page for a table is an between 1 and 32. It will
+ instruct the database to aim for this amount of tuples per page (8KB)
+ when updating or inserting rows, thereby tuning how agressive columns
+ will be compressed and/or transferred to the corresponding TOAST table.
+ Default is 4, which aims for tuplesizes less the 2KB.
+ Tuning the amount of tuples per page up, will increase the density
+ of tuples in the main table giving more speed for queries that only fetches
+ simple values or checking visibillity at the cost of having slower access
+ to the larger entries. Tuning the amount of tuples per page down will give
+ more tuple data in the main table thus faster access to data that would
+ otherwise have been moved to toast. This functionality can be viewed
+ as a way to vertically partition data into two files.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
<term><literal>autovacuum_enabled</>, <literal>toast.autovacuum_enabled</literal> (<type>boolean</>)</term>
<listitem>
<para>
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 1e619b1..6e6d0eb 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -15,6 +15,7 @@
#include "postgres.h"
+#include "access/tuptoaster.h"
#include "access/gist_private.h"
#include "access/hash.h"
#include "access/nbtree.h"
@@ -159,6 +160,13 @@ static relopt_int intRelOpts[] =
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
}, -1, 0, 2000000000
},
+ {
+ {
+ "tuples_per_page",
+ "Desired number of tuples per page (worst-case)",
+ RELOPT_KIND_HEAP
+ },TOAST_TUPLES_PER_PAGE , 1,32
+ },
/* list terminator */
{{NULL}}
};
@@ -1112,6 +1120,7 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
int numoptions;
static const relopt_parse_elt tab[] = {
{"fillfactor", RELOPT_TYPE_INT, offsetof(StdRdOptions, fillfactor)},
+ {"tuples_per_page", RELOPT_TYPE_INT, offsetof(StdRdOptions, tuples_per_page)},
{"autovacuum_enabled", RELOPT_TYPE_BOOL,
offsetof(StdRdOptions, autovacuum) +offsetof(AutoVacOpts, enabled)},
{"autovacuum_vacuum_threshold", RELOPT_TYPE_INT,
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 0ffdb6b..dc46bb0 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1883,7 +1883,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
Assert(!HeapTupleHasExternal(tup));
heaptup = tup;
}
- else if (HeapTupleHasExternal(tup) || tup->t_len > TOAST_TUPLE_THRESHOLD)
+ else if (HeapTupleHasExternal(tup) || tup->t_len > TOAST_TUPLE_THRESHOLD(relation))
heaptup = toast_insert_or_update(relation, tup, NULL, options);
else
heaptup = tup;
@@ -2595,7 +2595,7 @@ l2:
else
need_toast = (HeapTupleHasExternal(&oldtup) ||
HeapTupleHasExternal(newtup) ||
- newtup->t_len > TOAST_TUPLE_THRESHOLD);
+ newtup->t_len > TOAST_TUPLE_THRESHOLD(relation));
pagefree = PageGetHeapFreeSpace(page);
diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c
index 99235da..1e22fd7 100644
--- a/src/backend/access/heap/rewriteheap.c
+++ b/src/backend/access/heap/rewriteheap.c
@@ -573,7 +573,7 @@ raw_heap_insert(RewriteState state, HeapTuple tup)
Assert(!HeapTupleHasExternal(tup));
heaptup = tup;
}
- else if (HeapTupleHasExternal(tup) || tup->t_len > TOAST_TUPLE_THRESHOLD)
+ else if (HeapTupleHasExternal(tup) || tup->t_len > TOAST_TUPLE_THRESHOLD(state->rs_new_rel))
heaptup = toast_insert_or_update(state->rs_new_rel, tup, NULL,
HEAP_INSERT_SKIP_FSM |
(state->rs_use_wal ?
diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c
index 2af81df..47ae962 100644
--- a/src/backend/access/heap/tuptoaster.c
+++ b/src/backend/access/heap/tuptoaster.c
@@ -435,6 +435,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
bool toast_free[MaxHeapAttributeNumber];
bool toast_delold[MaxHeapAttributeNumber];
+ //fprintf(stderr,"entry point\n");
/*
* We should only ever be called for tuples of plain relations ---
* recursing on a toast rel is bad news.
@@ -594,7 +595,10 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
hoff = MAXALIGN(hoff);
Assert(hoff == newtup->t_data->t_hoff);
/* now convert to a limit on the tuple data size */
- maxDataLen = TOAST_TUPLE_TARGET - hoff;
+
+
+ maxDataLen = MaximumBytesPerTuple(RelationGetTuplesPerPage(rel,TOAST_TUPLES_PER_PAGE)) - hoff;
+ //fprintf(stderr,"tuplesize %u, target %u\n",heap_compute_data_size(tupleDesc,toast_values, toast_isnull),maxDataLen);
/*
* Look for attributes with attstorage 'x' to compress. Also find large
@@ -637,12 +641,14 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
i = biggest_attno;
if (att[i]->attstorage == 'x')
{
+ //fprintf(stderr,"trying to compress");
old_value = toast_values[i];
new_value = toast_compress_datum(old_value);
if (DatumGetPointer(new_value) != NULL)
{
/* successful compression */
+ //fprintf(stderr,"compression successfull");
if (toast_free[i])
pfree(DatumGetPointer(old_value));
toast_values[i] = new_value;
diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c
index fbdc423..b3c25e0 100644
--- a/src/backend/catalog/toasting.c
+++ b/src/backend/catalog/toasting.c
@@ -377,5 +377,5 @@ needs_toast_table(Relation rel)
tuple_length = MAXALIGN(offsetof(HeapTupleHeaderData, t_bits) +
BITMAPLEN(tupdesc->natts)) +
MAXALIGN(data_length);
- return (tuple_length > TOAST_TUPLE_THRESHOLD);
+ return (tuple_length > TOAST_TUPLE_THRESHOLD(rel));
}
diff --git a/src/include/access/tuptoaster.h b/src/include/access/tuptoaster.h
index a9f8572..82f09c1 100644
--- a/src/include/access/tuptoaster.h
+++ b/src/include/access/tuptoaster.h
@@ -52,9 +52,9 @@
*/
#define TOAST_TUPLES_PER_PAGE 4
-#define TOAST_TUPLE_THRESHOLD MaximumBytesPerTuple(TOAST_TUPLES_PER_PAGE)
+#define TOAST_TUPLE_THRESHOLD(rel) MaximumBytesPerTuple(RelationGetTuplesPerPage(rel,TOAST_TUPLES_PER_PAGE))
-#define TOAST_TUPLE_TARGET TOAST_TUPLE_THRESHOLD
+#define TOAST_TUPLE_TARGET(rel) TOAST_TUPLE_THRESHOLD(rel)
/*
* The code will also consider moving MAIN data out-of-line, but only as a
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index 1ab5158..f236fc0 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -241,12 +241,20 @@ typedef struct StdRdOptions
{
int32 vl_len_; /* varlena header (do not touch directly!) */
int fillfactor; /* page fill factor in percent (0..100) */
+ int tuples_per_page;
AutoVacOpts autovacuum; /* autovacuum-related options */
} StdRdOptions;
#define HEAP_MIN_FILLFACTOR 10
#define HEAP_DEFAULT_FILLFACTOR 100
+/* RelationGetTuplesPerPage
+ * Returns the desirec number of tuples per page.
+ */
+#define RelationGetTuplesPerPage(relation,defaulttpp) \
+ ((relation)->rd_options ? \
+ ((StdRdOptions *) (relation)->rd_options)->tuples_per_page : (defaulttpp))
+
/*
* RelationGetFillFactor
* Returns the relation's fillfactor. Note multiple eval of argument!