aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>2006-07-02 02:23:23 +0000
committerBruce Momjian <bruce@momjian.us>2006-07-02 02:23:23 +0000
commit277807bd9eba1645d8dfc9252fa29220c4a83751 (patch)
treefb3dca975d8371bd42e9e58d0b841db3fd6c4654 /src/backend/access
parent5d5c1416bf03efcf13cfd3b8f68a0bba199d70af (diff)
downloadpostgresql-277807bd9eba1645d8dfc9252fa29220c4a83751.tar.gz
postgresql-277807bd9eba1645d8dfc9252fa29220c4a83751.zip
Add FILLFACTOR to CREATE INDEX.
ITAGAKI Takahiro
Diffstat (limited to 'src/backend/access')
-rw-r--r--src/backend/access/common/heaptuple.c53
-rw-r--r--src/backend/access/gin/ginutil.c16
-rw-r--r--src/backend/access/gist/gist.c17
-rw-r--r--src/backend/access/gist/gistutil.c20
-rw-r--r--src/backend/access/gist/gistvacuum.c4
-rw-r--r--src/backend/access/gist/gistxlog.c4
-rw-r--r--src/backend/access/hash/hashpage.c5
-rw-r--r--src/backend/access/hash/hashutil.c15
-rw-r--r--src/backend/access/heap/heapam.c62
-rw-r--r--src/backend/access/heap/hio.c16
-rw-r--r--src/backend/access/index/genam.c47
-rw-r--r--src/backend/access/nbtree/nbtinsert.c21
-rw-r--r--src/backend/access/nbtree/nbtsort.c26
-rw-r--r--src/backend/access/nbtree/nbtutils.c15
-rw-r--r--src/backend/access/transam/xlogutils.c4
15 files changed, 283 insertions, 42 deletions
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c
index 7ec314379ba..edd90c8a56f 100644
--- a/src/backend/access/common/heaptuple.c
+++ b/src/backend/access/common/heaptuple.c
@@ -16,7 +16,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.107 2006/06/27 02:51:39 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.108 2006/07/02 02:23:18 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1738,3 +1738,54 @@ heap_addheader(int natts, /* max domain index */
return tuple;
}
+
+/*
+ * build_class_tuple
+ *
+ * XXX Natts_pg_class_fixed is a hack - see pg_class.h
+ */
+HeapTuple
+build_class_tuple(Form_pg_class pgclass, ArrayType *options)
+{
+ HeapTuple tuple;
+ HeapTupleHeader td;
+ Form_pg_class data; /* contents of tuple */
+ Size len;
+ Size size;
+ int hoff;
+
+ /* size of pg_class tuple with options */
+ if (options)
+ size = offsetof(FormData_pg_class, reloptions) + VARATT_SIZE(options);
+ else
+ size = CLASS_TUPLE_SIZE;
+
+ /* header needs no null bitmap */
+ hoff = offsetof(HeapTupleHeaderData, t_bits);
+ hoff += sizeof(Oid);
+ hoff = MAXALIGN(hoff);
+ len = hoff + size;
+
+ tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
+ tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
+
+ tuple->t_len = len;
+ ItemPointerSetInvalid(&(tuple->t_self));
+ tuple->t_tableOid = InvalidOid;
+
+ /* we don't bother to fill the Datum fields */
+
+ td->t_natts = Natts_pg_class_fixed;
+ td->t_hoff = hoff;
+ td->t_infomask = HEAP_HASOID;
+
+ data = (Form_pg_class) ((char *) td + hoff);
+ memcpy(data, pgclass, CLASS_TUPLE_SIZE);
+ if (options)
+ {
+ td->t_natts++;
+ memcpy(data->reloptions, options, VARATT_SIZE(options));
+ }
+
+ return tuple;
+}
diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c
index b9cb80a6cf1..17e041bc4a8 100644
--- a/src/backend/access/gin/ginutil.c
+++ b/src/backend/access/gin/ginutil.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gin/ginutil.c,v 1.1 2006/05/02 11:28:54 teodor Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gin/ginutil.c,v 1.2 2006/07/02 02:23:18 momjian Exp $
*-------------------------------------------------------------------------
*/
@@ -201,3 +201,17 @@ GinPageGetCopyPage( Page page ) {
return tmppage;
}
+
+Datum
+ginoption(PG_FUNCTION_ARGS)
+{
+ ArrayType *options = (ArrayType *) PG_GETARG_POINTER(0);
+
+ if (options != NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("GIN does not support parameters at all")));
+
+ /* Do not use PG_RETURN_NULL. */
+ PG_RETURN_BYTEA_P(NULL);
+}
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index 39ff702c3d1..4137ab4426f 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.139 2006/06/28 12:00:14 teodor Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.140 2006/07/02 02:23:18 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -44,6 +44,7 @@ static void gistbuildCallback(Relation index,
void *state);
static void gistdoinsert(Relation r,
IndexTuple itup,
+ Size freespace,
GISTSTATE *GISTstate);
static void gistfindleaf(GISTInsertState *state,
GISTSTATE *giststate);
@@ -197,7 +198,8 @@ gistbuildCallback(Relation index,
* you're inserting single tups, but not when you're initializing the
* whole index at once.
*/
- gistdoinsert(index, itup, &buildstate->giststate);
+ gistdoinsert(index, itup, IndexGetPageFreeSpace(index),
+ &buildstate->giststate);
buildstate->indtuples += 1;
MemoryContextSwitchTo(oldCtx);
@@ -236,7 +238,7 @@ gistinsert(PG_FUNCTION_ARGS)
values, isnull, true /* size is currently bogus */);
itup->t_tid = *ht_ctid;
- gistdoinsert(r, itup, &giststate);
+ gistdoinsert(r, itup, 0, &giststate);
/* cleanup */
freeGISTstate(&giststate);
@@ -253,7 +255,7 @@ gistinsert(PG_FUNCTION_ARGS)
* so it does not bother releasing palloc'd allocations.
*/
static void
-gistdoinsert(Relation r, IndexTuple itup, GISTSTATE *giststate)
+gistdoinsert(Relation r, IndexTuple itup, Size freespace, GISTSTATE *giststate)
{
GISTInsertState state;
@@ -263,6 +265,7 @@ gistdoinsert(Relation r, IndexTuple itup, GISTSTATE *giststate)
state.itup[0] = (IndexTuple) palloc(IndexTupleSize(itup));
memcpy(state.itup[0], itup, IndexTupleSize(itup));
state.ituplen = 1;
+ state.freespace = freespace;
state.r = r;
state.key = itup->t_tid;
state.needInsertComplete = true;
@@ -294,7 +297,11 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate)
*/
- if (gistnospace(state->stack->page, state->itup, state->ituplen, (is_leaf) ? InvalidOffsetNumber : state->stack->childoffnum))
+ /*
+ * XXX: If we want to change fillfactors between node and leaf,
+ * fillfactor = (is_leaf ? state->leaf_fillfactor : state->node_fillfactor)
+ */
+ if (gistnospace(state->stack->page, state->itup, state->ituplen, (is_leaf) ? InvalidOffsetNumber : state->stack->childoffnum, state->freespace))
{
/* no space for insertion */
IndexTuple *itvec;
diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c
index 3be4fd31f58..ae1fbc73201 100644
--- a/src/backend/access/gist/gistutil.c
+++ b/src/backend/access/gist/gistutil.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gist/gistutil.c,v 1.16 2006/06/28 12:00:14 teodor Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gist/gistutil.c,v 1.17 2006/07/02 02:23:18 momjian Exp $
*-------------------------------------------------------------------------
*/
#include "postgres.h"
@@ -58,9 +58,9 @@ gistfillbuffer(Relation r, Page page, IndexTuple *itup,
* Check space for itup vector on page
*/
bool
-gistnospace(Page page, IndexTuple *itvec, int len, OffsetNumber todelete)
+gistnospace(Page page, IndexTuple *itvec, int len, OffsetNumber todelete, Size freespace)
{
- unsigned int size = 0, deleted = 0;
+ unsigned int size = freespace, deleted = 0;
int i;
for (i = 0; i < len; i++)
@@ -82,6 +82,7 @@ gistfitpage(IndexTuple *itvec, int len) {
for(i=0;i<len;i++)
size += IndexTupleSize(itvec[i]) + sizeof(ItemIdData);
+ /* TODO: Consider fillfactor */
return (size <= GiSTPageSize);
}
@@ -634,3 +635,16 @@ gistNewBuffer(Relation r)
return buffer;
}
+
+Datum
+gistoption(PG_FUNCTION_ARGS)
+{
+#define GIST_DEFAULT_FILLFACTOR 90
+#define GIST_MIN_FILLFACTOR 50
+
+ ArrayType *options = (ArrayType *) PG_GETARG_POINTER(0);
+
+ /* Use index common routine. */
+ PG_RETURN_BYTEA_P(genam_option(options,
+ GIST_MIN_FILLFACTOR, GIST_DEFAULT_FILLFACTOR));
+}
diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c
index a47d81db78e..faf7661f96a 100644
--- a/src/backend/access/gist/gistvacuum.c
+++ b/src/backend/access/gist/gistvacuum.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.22 2006/05/19 11:10:25 teodor Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.23 2006/07/02 02:23:18 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -376,7 +376,7 @@ gistVacuumUpdate(GistVacuum *gv, BlockNumber blkno, bool needunion)
if (curlenaddon)
{
/* insert updated tuples */
- if (gistnospace(tempPage, addon, curlenaddon, InvalidOffsetNumber)) {
+ if (gistnospace(tempPage, addon, curlenaddon, InvalidOffsetNumber, 0)) {
/* there is no space on page to insert tuples */
res = vacuumSplitPage(gv, tempPage, buffer, addon, curlenaddon);
tempPage=NULL; /* vacuumSplitPage() free tempPage */
diff --git a/src/backend/access/gist/gistxlog.c b/src/backend/access/gist/gistxlog.c
index c4291c01f81..fbae13ef039 100644
--- a/src/backend/access/gist/gistxlog.c
+++ b/src/backend/access/gist/gistxlog.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gist/gistxlog.c,v 1.20 2006/05/19 17:15:41 teodor Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gist/gistxlog.c,v 1.21 2006/07/02 02:23:18 momjian Exp $
*-------------------------------------------------------------------------
*/
#include "postgres.h"
@@ -690,7 +690,7 @@ gistContinueInsert(gistIncompleteInsert *insert)
* that wiil be enough space....
*/
- if (gistnospace(pages[0], itup, lenitup, *todelete))
+ if (gistnospace(pages[0], itup, lenitup, *todelete, 0))
{
/* no space left on page, so we must split */
diff --git a/src/backend/access/hash/hashpage.c b/src/backend/access/hash/hashpage.c
index 488a7c5819f..bed0b5dbd72 100644
--- a/src/backend/access/hash/hashpage.c
+++ b/src/backend/access/hash/hashpage.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/hash/hashpage.c,v 1.57 2006/03/31 23:32:05 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/hash/hashpage.c,v 1.58 2006/07/02 02:23:18 momjian Exp $
*
* NOTES
* Postgres hash pages look like ordinary relation pages. The opaque
@@ -30,6 +30,7 @@
#include "access/genam.h"
#include "access/hash.h"
+#include "catalog/index.h"
#include "miscadmin.h"
#include "storage/lmgr.h"
#include "utils/lsyscache.h"
@@ -231,7 +232,7 @@ _hash_metapinit(Relation rel)
RelationGetDescr(rel)->attrs[0]->atttypmod);
item_width = MAXALIGN(sizeof(IndexTupleData)) + MAXALIGN(data_width) +
sizeof(ItemIdData); /* include the line pointer */
- ffactor = (BLCKSZ * 3 / 4) / item_width;
+ ffactor = BLCKSZ * IndexGetFillFactor(rel) / 100 / item_width;
/* keep to a sane range */
if (ffactor < 10)
ffactor = 10;
diff --git a/src/backend/access/hash/hashutil.c b/src/backend/access/hash/hashutil.c
index 65b8ef948c2..fbee1fdc2aa 100644
--- a/src/backend/access/hash/hashutil.c
+++ b/src/backend/access/hash/hashutil.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/hash/hashutil.c,v 1.47 2006/03/05 15:58:21 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/hash/hashutil.c,v 1.48 2006/07/02 02:23:18 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -173,3 +173,16 @@ _hash_checkpage(Relation rel, Buffer buf, int flags)
errhint("Please REINDEX it.")));
}
}
+
+Datum
+hashoption(PG_FUNCTION_ARGS)
+{
+#define HASH_MIN_FILLFACTOR 50
+#define HASH_DEFAULT_FILLFACTOR 75
+
+ ArrayType *options = (ArrayType *) PG_GETARG_POINTER(0);
+
+ /* Use index common routine. */
+ PG_RETURN_BYTEA_P(genam_option(options,
+ HASH_MIN_FILLFACTOR, HASH_DEFAULT_FILLFACTOR));
+}
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 15556fda538..cf3344c2009 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.213 2006/05/28 02:27:08 alvherre Exp $
+ * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.214 2006/07/02 02:23:18 momjian Exp $
*
*
* INTERFACE ROUTINES
@@ -46,9 +46,13 @@
#include "access/xlogutils.h"
#include "catalog/catalog.h"
#include "catalog/namespace.h"
+#include "commands/defrem.h"
#include "miscadmin.h"
+#include "nodes/parsenodes.h"
+#include "parser/parse_clause.h"
#include "pgstat.h"
#include "storage/procarray.h"
+#include "utils/catcache.h"
#include "utils/inval.h"
#include "utils/relcache.h"
@@ -3588,3 +3592,59 @@ heap_desc(StringInfo buf, uint8 xl_info, char *rec)
else
appendStringInfo(buf, "UNKNOWN");
}
+
+/*
+ * Parse options for heaps.
+ *
+ * relkind Kind of relation
+ * options Options as text[]
+ */
+bytea *
+heap_option(char relkind, ArrayType *options)
+{
+ /*
+ * XXX: What fillfactor should be default?
+ * overriding databases:
+ * - Oracle, DB2 = 90%
+ * - SQL Server = 100%
+ * non-overriding database:
+ * - Firebird = 70%
+ */
+#define HEAP_MIN_FILLFACTOR 50
+#define HEAP_DEFAULT_FILLFACTOR 100
+
+ int fillfactor;
+ HeapOption *result;
+
+ DefElem kwds[] =
+ {
+ { T_DefElem, "fillfactor" },
+ };
+
+ /*
+ * parse options
+ */
+ OptionParse(options, lengthof(kwds), kwds, true);
+
+ /* 0: fillfactor */
+ if (kwds[0].arg)
+ fillfactor = (int) defGetInt64(&kwds[0]);
+ else
+ fillfactor = HEAP_DEFAULT_FILLFACTOR;
+ if (fillfactor < HEAP_MIN_FILLFACTOR || 100 < fillfactor)
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("fillfactor=%d should be between %d and 100",
+ fillfactor, HEAP_MIN_FILLFACTOR)));
+ }
+
+ /*
+ * build option
+ */
+ result = (HeapOption *)
+ MemoryContextAlloc(CacheMemoryContext, sizeof(HeapOption));
+ VARATT_SIZEP(result) = sizeof(HeapOption);
+ result->fillfactor = fillfactor;
+ return (bytea *) result;
+}
diff --git a/src/backend/access/heap/hio.c b/src/backend/access/heap/hio.c
index ccaaacefea8..82fb0a3268a 100644
--- a/src/backend/access/heap/hio.c
+++ b/src/backend/access/heap/hio.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/heap/hio.c,v 1.61 2006/03/05 15:58:21 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/heap/hio.c,v 1.62 2006/07/02 02:23:18 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -102,12 +102,18 @@ RelationGetBufferForTuple(Relation relation, Size len,
{
Buffer buffer = InvalidBuffer;
Page pageHeader;
- Size pageFreeSpace;
+ Size pageFreeSpace,
+ freespace;
BlockNumber targetBlock,
otherBlock;
bool needLock;
+ if (relation->rd_options == NULL)
+ elog(ERROR, "RelationGetBufferForTuple %s IS NULL", RelationGetRelationName(relation));
+ Assert(relation->rd_options != NULL);
+
len = MAXALIGN(len); /* be conservative */
+ freespace = HeapGetPageFreeSpace(relation);
/*
* If we're gonna fail for oversize tuple, do it right away
@@ -146,7 +152,7 @@ RelationGetBufferForTuple(Relation relation, Size len,
* We have no cached target page, so ask the FSM for an initial
* target.
*/
- targetBlock = GetPageWithFreeSpace(&relation->rd_node, len);
+ targetBlock = GetPageWithFreeSpace(&relation->rd_node, len + freespace);
/*
* If the FSM knows nothing of the rel, try the last page before we
@@ -202,7 +208,7 @@ RelationGetBufferForTuple(Relation relation, Size len,
*/
pageHeader = (Page) BufferGetPage(buffer);
pageFreeSpace = PageGetFreeSpace(pageHeader);
- if (len <= pageFreeSpace)
+ if (len + freespace <= pageFreeSpace)
{
/* use this page as future insert target, too */
relation->rd_targblock = targetBlock;
@@ -235,7 +241,7 @@ RelationGetBufferForTuple(Relation relation, Size len,
targetBlock = RecordAndGetPageWithFreeSpace(&relation->rd_node,
targetBlock,
pageFreeSpace,
- len);
+ len + freespace);
}
/*
diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c
index 56eabbaf421..cfc2a833cd3 100644
--- a/src/backend/access/index/genam.c
+++ b/src/backend/access/index/genam.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.55 2006/05/07 01:21:30 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.56 2006/07/02 02:23:18 momjian Exp $
*
* NOTES
* many of the old access method routines have been turned into
@@ -21,8 +21,12 @@
#include "access/genam.h"
#include "access/heapam.h"
+#include "commands/defrem.h"
#include "miscadmin.h"
+#include "nodes/parsenodes.h"
+#include "parser/parse_clause.h"
#include "pgstat.h"
+#include "utils/catcache.h"
/* ----------------------------------------------------------------
@@ -260,3 +264,44 @@ systable_endscan(SysScanDesc sysscan)
pfree(sysscan);
}
+
+/*
+ * Parse options for generic indexes.
+ */
+bytea *
+genam_option(ArrayType *options,
+ int minFillfactor, int defaultFillfactor)
+{
+ int fillfactor;
+ IndexOption *result;
+
+ DefElem kwds[] =
+ {
+ { T_DefElem, "fillfactor" },
+ };
+
+ /*
+ * parse options
+ */
+ OptionParse(options, lengthof(kwds), kwds, true);
+
+ /* 0: fillfactor */
+ if (kwds[0].arg)
+ fillfactor = (int) defGetInt64(&kwds[0]);
+ else
+ fillfactor = defaultFillfactor;
+ if (fillfactor < minFillfactor || 100 < fillfactor)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("fillfactor=%d should be between %d and 100",
+ fillfactor, minFillfactor)));
+
+ /*
+ * build options
+ */
+ result = (IndexOption *)
+ MemoryContextAlloc(CacheMemoryContext, sizeof(IndexOption));
+ VARATT_SIZEP(result) = sizeof(IndexOption);
+ result->fillfactor = fillfactor;
+ return (bytea *) result;
+}
diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c
index 89f8810bde5..3b78843101e 100644
--- a/src/backend/access/nbtree/nbtinsert.c
+++ b/src/backend/access/nbtree/nbtinsert.c
@@ -8,13 +8,14 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.137 2006/05/08 00:00:09 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.138 2006/07/02 02:23:18 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
+#include "access/genam.h"
#include "access/heapam.h"
#include "access/nbtree.h"
#include "miscadmin.h"
@@ -25,6 +26,7 @@ typedef struct
{
/* context data for _bt_checksplitloc */
Size newitemsz; /* size of new item to be inserted */
+ int fillfactor; /* used when insert at right most */
bool is_leaf; /* T if splitting a leaf page */
bool is_rightmost; /* T if splitting a rightmost page */
@@ -986,14 +988,11 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
* it needs to go into!)
*
* If the page is the rightmost page on its level, we instead try to arrange
- * for twice as much free space on the right as on the left. In this way,
+ * for reserving (100-fillfactor)% of free space on left page. In this way,
* when we are inserting successively increasing keys (consider sequences,
- * timestamps, etc) we will end up with a tree whose pages are about 67% full,
+ * timestamps, etc) we will end up with a tree whose pages are about fillfactor% full,
* instead of the 50% full result that we'd get without this special case.
- * (We could bias it even further to make the initially-loaded tree more full.
- * But since the steady-state load for a btree is about 70%, we'd likely just
- * be making more page-splitting work for ourselves later on, when we start
- * seeing updates to existing tuples.)
+ * This is the same as initially-loaded tree.
*
* We are passed the intended insert position of the new tuple, expressed as
* the offsetnumber of the tuple it must go in front of. (This could be
@@ -1027,6 +1026,7 @@ _bt_findsplitloc(Relation rel,
/* Passed-in newitemsz is MAXALIGNED but does not include line pointer */
newitemsz += sizeof(ItemIdData);
state.newitemsz = newitemsz;
+ state.fillfactor = IndexGetFillFactor(rel);
state.is_leaf = P_ISLEAF(opaque);
state.is_rightmost = P_RIGHTMOST(opaque);
state.have_split = false;
@@ -1157,10 +1157,11 @@ _bt_checksplitloc(FindSplitData *state, OffsetNumber firstright,
if (state->is_rightmost)
{
/*
- * On a rightmost page, try to equalize right free space with
- * twice the left free space. See comments for _bt_findsplitloc.
+ * On a rightmost page, try to reserve (100-fillfactor)% of
+ * free space on left page. See comments for _bt_findsplitloc.
*/
- delta = (2 * leftfree) - rightfree;
+ delta = (state->fillfactor * leftfree)
+ - ((100 - state->fillfactor) * rightfree);
}
else
{
diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c
index e7293b47b03..05785d98eb5 100644
--- a/src/backend/access/nbtree/nbtsort.c
+++ b/src/backend/access/nbtree/nbtsort.c
@@ -56,13 +56,14 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.102 2006/06/27 16:53:02 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.103 2006/07/02 02:23:19 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
+#include "access/genam.h"
#include "access/nbtree.h"
#include "access/xlog.h"
#include "miscadmin.h"
@@ -120,6 +121,7 @@ typedef struct BTWriteState
static Page _bt_blnewpage(uint32 level);
+static Size _bt_full_threshold(Relation index, Size pagesize, bool leaf);
static BTPageState *_bt_pagestate(BTWriteState *wstate, uint32 level);
static void _bt_slideleft(Page page);
static void _bt_sortaddtup(Page page, Size itemsize,
@@ -328,6 +330,22 @@ _bt_blwritepage(BTWriteState *wstate, Page page, BlockNumber blkno)
}
/*
+ * The steady-state load factor for btrees is usually estimated at 70%.
+ * We choose to pack leaf pages to 90% and upper pages to 70% as defaults.
+ */
+static Size
+_bt_full_threshold(Relation index, Size pagesize, bool leaf)
+{
+ int fillfactor = IndexGetFillFactor(index);
+ if (!leaf)
+ {
+ /* XXX: Is this reasonable? */
+ fillfactor = Max(70, 3 * fillfactor - 200);
+ }
+ return pagesize * (100 - fillfactor) / 100;
+}
+
+/*
* allocate and initialize a new BTPageState. the returned structure
* is suitable for immediate use by _bt_buildadd.
*/
@@ -347,10 +365,8 @@ _bt_pagestate(BTWriteState *wstate, uint32 level)
state->btps_lastoff = P_HIKEY;
state->btps_level = level;
/* set "full" threshold based on level. See notes at head of file. */
- if (level > 0)
- state->btps_full = (PageGetPageSize(state->btps_page) * 3) / 10;
- else
- state->btps_full = PageGetPageSize(state->btps_page) / 10;
+ state->btps_full = _bt_full_threshold(wstate->index,
+ PageGetPageSize(state->btps_page), level == 0);
/* no parent level, yet */
state->btps_next = NULL;
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index 5db8f552884..93a9b0df653 100644
--- a/src/backend/access/nbtree/nbtutils.c
+++ b/src/backend/access/nbtree/nbtutils.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.74 2006/05/08 00:00:10 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.75 2006/07/02 02:23:19 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1079,3 +1079,16 @@ BTreeShmemInit(void)
else
Assert(found);
}
+
+Datum
+btoption(PG_FUNCTION_ARGS)
+{
+#define BTREE_MIN_FILLFACTOR 50
+#define BTREE_DEFAULT_FILLFACTOR 90
+
+ ArrayType *options = (ArrayType *) PG_GETARG_POINTER(0);
+
+ /* Use index common routine. */
+ PG_RETURN_BYTEA_P(genam_option(options,
+ BTREE_MIN_FILLFACTOR, BTREE_DEFAULT_FILLFACTOR));
+}
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 39d3e041e45..da30e39b42d 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -11,7 +11,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/access/transam/xlogutils.c,v 1.44 2006/04/14 20:27:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlogutils.c,v 1.45 2006/07/02 02:23:19 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -337,7 +337,7 @@ _xl_remove_hash_entry(XLogRelDesc *rdesc)
RelationCloseSmgr(&(rdesc->reldata));
memset(rdesc, 0, sizeof(XLogRelDesc));
- memset(tpgc, 0, sizeof(FormData_pg_class));
+ memset(tpgc, 0, CLASS_TUPLE_SIZE);
rdesc->reldata.rd_rel = tpgc;
}