diff options
author | Bruce Momjian <bruce@momjian.us> | 2006-07-02 02:23:23 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2006-07-02 02:23:23 +0000 |
commit | 277807bd9eba1645d8dfc9252fa29220c4a83751 (patch) | |
tree | fb3dca975d8371bd42e9e58d0b841db3fd6c4654 /src/backend/access | |
parent | 5d5c1416bf03efcf13cfd3b8f68a0bba199d70af (diff) | |
download | postgresql-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.c | 53 | ||||
-rw-r--r-- | src/backend/access/gin/ginutil.c | 16 | ||||
-rw-r--r-- | src/backend/access/gist/gist.c | 17 | ||||
-rw-r--r-- | src/backend/access/gist/gistutil.c | 20 | ||||
-rw-r--r-- | src/backend/access/gist/gistvacuum.c | 4 | ||||
-rw-r--r-- | src/backend/access/gist/gistxlog.c | 4 | ||||
-rw-r--r-- | src/backend/access/hash/hashpage.c | 5 | ||||
-rw-r--r-- | src/backend/access/hash/hashutil.c | 15 | ||||
-rw-r--r-- | src/backend/access/heap/heapam.c | 62 | ||||
-rw-r--r-- | src/backend/access/heap/hio.c | 16 | ||||
-rw-r--r-- | src/backend/access/index/genam.c | 47 | ||||
-rw-r--r-- | src/backend/access/nbtree/nbtinsert.c | 21 | ||||
-rw-r--r-- | src/backend/access/nbtree/nbtsort.c | 26 | ||||
-rw-r--r-- | src/backend/access/nbtree/nbtutils.c | 15 | ||||
-rw-r--r-- | src/backend/access/transam/xlogutils.c | 4 |
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; } |