Commit 10dd8df6 authored by Teodor Sigaev's avatar Teodor Sigaev

Reduce size of critical section and remove call of user-defined functions in

insertion and deletion, modify gistSplit() to do not use buffers.

 TODO: gistvacuumcleanup and XLOG
parent 12049d34
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/gist/gistutil.c,v 1.10 2006/03/05 15:58:20 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/gist/gistutil.c,v 1.11 2006/05/10 09:19:54 teodor Exp $
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres.h" #include "postgres.h"
...@@ -81,15 +81,31 @@ gistfillbuffer(Relation r, Page page, IndexTuple *itup, ...@@ -81,15 +81,31 @@ gistfillbuffer(Relation r, Page page, IndexTuple *itup,
* Check space for itup vector on page * Check space for itup vector on page
*/ */
bool bool
gistnospace(Page page, IndexTuple *itvec, int len) gistnospace(Page page, IndexTuple *itvec, int len, OffsetNumber todelete)
{ {
unsigned int size = 0; unsigned int size = 0, deleted = 0;
int i; int i;
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
size += IndexTupleSize(itvec[i]) + sizeof(ItemIdData); size += IndexTupleSize(itvec[i]) + sizeof(ItemIdData);
return (PageGetFreeSpace(page) < size); if ( todelete != InvalidOffsetNumber ) {
IndexTuple itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, todelete));
deleted = IndexTupleSize(itup) + sizeof(ItemIdData);
}
return (PageGetFreeSpace(page) + deleted < size);
}
bool
gistfitpage(IndexTuple *itvec, int len) {
int i;
Size size=0;
for(i=0;i<len;i++)
size += IndexTupleSize(itvec[i]) + sizeof(ItemIdData);
return (size <= GiSTPageSize);
} }
/* /*
...@@ -107,7 +123,7 @@ gistextractbuffer(Buffer buffer, int *len /* out */ ) ...@@ -107,7 +123,7 @@ gistextractbuffer(Buffer buffer, int *len /* out */ )
*len = maxoff; *len = maxoff;
itvec = palloc(sizeof(IndexTuple) * maxoff); itvec = palloc(sizeof(IndexTuple) * maxoff);
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
itvec[i - 1] = (IndexTuple) PageGetItem(p, PageGetItemId(p, i)); itvec[i - FirstOffsetNumber] = (IndexTuple) PageGetItem(p, PageGetItemId(p, i));
return itvec; return itvec;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.19 2006/05/02 22:25:10 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.20 2006/05/10 09:19:54 teodor Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -85,10 +85,7 @@ gistVacuumUpdate(GistVacuum *gv, BlockNumber blkno, bool needunion) ...@@ -85,10 +85,7 @@ gistVacuumUpdate(GistVacuum *gv, BlockNumber blkno, bool needunion)
if (GistPageIsLeaf(page)) if (GistPageIsLeaf(page))
{ {
if (GistTuplesDeleted(page)) if (GistTuplesDeleted(page))
{
needunion = needwrite = true; needunion = needwrite = true;
GistClearTuplesDeleted(page);
}
} }
else else
{ {
...@@ -157,30 +154,54 @@ gistVacuumUpdate(GistVacuum *gv, BlockNumber blkno, bool needunion) ...@@ -157,30 +154,54 @@ gistVacuumUpdate(GistVacuum *gv, BlockNumber blkno, bool needunion)
if (curlenaddon) if (curlenaddon)
{ {
/* insert updated tuples */ /* insert updated tuples */
if (gistnospace(page, addon, curlenaddon)) if (gistnospace(page, addon, curlenaddon, InvalidOffsetNumber))
{ {
/* there is no space on page to insert tuples */ /* there is no space on page to insert tuples */
IndexTuple *vec; IndexTuple *vec;
SplitedPageLayout *dist = NULL, SplitedPageLayout *dist = NULL,
*ptr; *ptr;
int i; int i, veclen=0;
MemoryContext oldCtx = MemoryContextSwitchTo(gv->opCtx); MemoryContext oldCtx = MemoryContextSwitchTo(gv->opCtx);
vec = gistextractbuffer(buffer, &(res.ituplen)); vec = gistextractbuffer(buffer, &veclen);
vec = gistjoinvector(vec, &(res.ituplen), addon, curlenaddon); vec = gistjoinvector(vec, &veclen, addon, curlenaddon);
res.itup = gistSplit(gv->index, buffer, vec, &(res.ituplen), &dist, &(gv->giststate)); dist = gistSplit(gv->index, page, vec, veclen, &(gv->giststate));
MemoryContextSwitchTo(oldCtx); MemoryContextSwitchTo(oldCtx);
vec = (IndexTuple *) palloc(sizeof(IndexTuple) * res.ituplen); if (blkno != GIST_ROOT_BLKNO) {
for (i = 0; i < res.ituplen; i++) /* if non-root split then we should not allocate new buffer */
{ dist->buffer = buffer;
vec[i] = (IndexTuple) palloc(IndexTupleSize(res.itup[i])); dist->page = BufferGetPage(dist->buffer);
memcpy(vec[i], res.itup[i], IndexTupleSize(res.itup[i])); GistPageGetOpaque(dist->page)->flags = 0;
} }
res.itup = vec;
for (ptr = dist; ptr; ptr = ptr->next) res.itup = (IndexTuple *) palloc(sizeof(IndexTuple) * veclen);
{ res.ituplen = 0;
/* make new pages and fills them */
for (ptr = dist; ptr; ptr = ptr->next) {
char *data;
if ( ptr->buffer == InvalidBuffer ) {
ptr->buffer = gistNewBuffer( gv->index );
GISTInitBuffer( ptr->buffer, 0 );
ptr->page = BufferGetPage(ptr->buffer);
}
ptr->block.blkno = BufferGetBlockNumber( ptr->buffer );
data = (char*)(ptr->list);
for(i=0;i<ptr->block.num;i++) {
if ( PageAddItem(ptr->page, (Item)data, IndexTupleSize((IndexTuple)data), i+FirstOffsetNumber, LP_USED) == InvalidOffsetNumber )
elog(ERROR, "failed to add item to index page in \"%s\"", RelationGetRelationName(gv->index));
data += IndexTupleSize((IndexTuple)data);
}
ItemPointerSetBlockNumber(&(ptr->itup->t_tid), ptr->block.blkno);
res.itup[ res.ituplen ] = (IndexTuple)palloc(IndexTupleSize(ptr->itup));
memcpy( res.itup[ res.ituplen ], ptr->itup, IndexTupleSize(ptr->itup) );
res.ituplen++;
MarkBufferDirty(ptr->buffer); MarkBufferDirty(ptr->buffer);
} }
...@@ -218,10 +239,9 @@ gistVacuumUpdate(GistVacuum *gv, BlockNumber blkno, bool needunion) ...@@ -218,10 +239,9 @@ gistVacuumUpdate(GistVacuum *gv, BlockNumber blkno, bool needunion)
for (ptr = dist; ptr; ptr = ptr->next) for (ptr = dist; ptr; ptr = ptr->next)
{ {
/* we must keep the buffer lock on the head page */ /* we must keep the buffer pin on the head page */
if (BufferGetBlockNumber(ptr->buffer) != blkno) if (BufferGetBlockNumber(ptr->buffer) != blkno)
LockBuffer(ptr->buffer, GIST_UNLOCK); UnlockReleaseBuffer( ptr->buffer );
ReleaseBuffer(ptr->buffer);
} }
if (blkno == GIST_ROOT_BLKNO) if (blkno == GIST_ROOT_BLKNO)
...@@ -294,6 +314,7 @@ gistVacuumUpdate(GistVacuum *gv, BlockNumber blkno, bool needunion) ...@@ -294,6 +314,7 @@ gistVacuumUpdate(GistVacuum *gv, BlockNumber blkno, bool needunion)
if (needwrite) if (needwrite)
{ {
MarkBufferDirty(buffer); MarkBufferDirty(buffer);
GistClearTuplesDeleted(page);
if (!gv->index->rd_istemp) if (!gv->index->rd_istemp)
{ {
...@@ -570,14 +591,7 @@ gistbulkdelete(PG_FUNCTION_ARGS) ...@@ -570,14 +591,7 @@ gistbulkdelete(PG_FUNCTION_ARGS)
/* /*
* Remove deletable tuples from page * Remove deletable tuples from page
*
* XXX try to make this critical section shorter. Could do it
* by separating the callback loop from the actual tuple deletion,
* but that would affect the definition of the todelete[] array
* passed into the WAL record (because the indexes would all be
* pre-deletion).
*/ */
START_CRIT_SECTION();
maxoff = PageGetMaxOffsetNumber(page); maxoff = PageGetMaxOffsetNumber(page);
...@@ -588,13 +602,9 @@ gistbulkdelete(PG_FUNCTION_ARGS) ...@@ -588,13 +602,9 @@ gistbulkdelete(PG_FUNCTION_ARGS)
if (callback(&(idxtuple->t_tid), callback_state)) if (callback(&(idxtuple->t_tid), callback_state))
{ {
PageIndexTupleDelete(page, i); todelete[ntodelete] = i-ntodelete;
todelete[ntodelete] = i;
i--;
maxoff--;
ntodelete++; ntodelete++;
stats->std.tuples_removed += 1; stats->std.tuples_removed += 1;
Assert(maxoff == PageGetMaxOffsetNumber(page));
} }
else else
stats->std.num_index_tuples += 1; stats->std.num_index_tuples += 1;
...@@ -602,10 +612,14 @@ gistbulkdelete(PG_FUNCTION_ARGS) ...@@ -602,10 +612,14 @@ gistbulkdelete(PG_FUNCTION_ARGS)
if (ntodelete) if (ntodelete)
{ {
GistMarkTuplesDeleted(page); START_CRIT_SECTION();
MarkBufferDirty(buffer); MarkBufferDirty(buffer);
for(i=0;i<ntodelete;i++)
PageIndexTupleDelete(page, todelete[i]);
GistMarkTuplesDeleted(page);
if (!rel->rd_istemp) if (!rel->rd_istemp)
{ {
XLogRecData *rdata; XLogRecData *rdata;
...@@ -627,10 +641,11 @@ gistbulkdelete(PG_FUNCTION_ARGS) ...@@ -627,10 +641,11 @@ gistbulkdelete(PG_FUNCTION_ARGS)
} }
else else
PageSetLSN(page, XLogRecPtrForTemp); PageSetLSN(page, XLogRecPtrForTemp);
}
END_CRIT_SECTION(); END_CRIT_SECTION();
} }
}
else else
{ {
/* check for split proceeded after look at parent */ /* check for split proceeded after look at parent */
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/gist/gistxlog.c,v 1.15 2006/04/03 16:45:50 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/gist/gistxlog.c,v 1.16 2006/05/10 09:19:54 teodor Exp $
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres.h" #include "postgres.h"
...@@ -625,7 +625,7 @@ gistContinueInsert(gistIncompleteInsert *insert) ...@@ -625,7 +625,7 @@ gistContinueInsert(gistIncompleteInsert *insert)
} }
} }
if (gistnospace(pages[numbuffer - 1], itup, lenitup)) if (gistnospace(pages[numbuffer - 1], itup, lenitup, InvalidOffsetNumber))
{ {
/* no space left on page, so we must split */ /* no space left on page, so we must split */
buffers[numbuffer] = ReadBuffer(index, P_NEW); buffers[numbuffer] = ReadBuffer(index, P_NEW);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.12 2006/03/30 23:03:10 tgl Exp $ * $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.13 2006/05/10 09:19:54 teodor Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -138,6 +138,8 @@ typedef struct SplitedPageLayout ...@@ -138,6 +138,8 @@ typedef struct SplitedPageLayout
gistxlogPage block; gistxlogPage block;
IndexTupleData *list; IndexTupleData *list;
int lenlist; int lenlist;
IndexTuple itup; /* union key for page */
Page page; /* to operate */
Buffer buffer; /* to write after all proceed */ Buffer buffer; /* to write after all proceed */
struct SplitedPageLayout *next; struct SplitedPageLayout *next;
...@@ -234,8 +236,8 @@ extern void freeGISTstate(GISTSTATE *giststate); ...@@ -234,8 +236,8 @@ extern void freeGISTstate(GISTSTATE *giststate);
extern void gistmakedeal(GISTInsertState *state, GISTSTATE *giststate); extern void gistmakedeal(GISTInsertState *state, GISTSTATE *giststate);
extern void gistnewroot(Relation r, Buffer buffer, IndexTuple *itup, int len, ItemPointer key); extern void gistnewroot(Relation r, Buffer buffer, IndexTuple *itup, int len, ItemPointer key);
extern IndexTuple *gistSplit(Relation r, Buffer buffer, IndexTuple *itup, extern SplitedPageLayout *gistSplit(Relation r, Page page, IndexTuple *itup,
int *len, SplitedPageLayout **dist, GISTSTATE *giststate); int len, GISTSTATE *giststate);
extern GISTInsertStack *gistFindPath(Relation r, BlockNumber child); extern GISTInsertStack *gistFindPath(Relation r, BlockNumber child);
...@@ -261,11 +263,16 @@ extern Datum gistgettuple(PG_FUNCTION_ARGS); ...@@ -261,11 +263,16 @@ extern Datum gistgettuple(PG_FUNCTION_ARGS);
extern Datum gistgetmulti(PG_FUNCTION_ARGS); extern Datum gistgetmulti(PG_FUNCTION_ARGS);
/* gistutil.c */ /* gistutil.c */
#define GiSTPageSize \
( BLCKSZ - SizeOfPageHeaderData - MAXALIGN(sizeof(GISTPageOpaqueData)) )
extern bool gistfitpage(IndexTuple *itvec, int len);
extern bool gistnospace(Page page, IndexTuple *itvec, int len, OffsetNumber todelete);
extern void gistcheckpage(Relation rel, Buffer buf); extern void gistcheckpage(Relation rel, Buffer buf);
extern Buffer gistNewBuffer(Relation r); extern Buffer gistNewBuffer(Relation r);
extern OffsetNumber gistfillbuffer(Relation r, Page page, IndexTuple *itup, extern OffsetNumber gistfillbuffer(Relation r, Page page, IndexTuple *itup,
int len, OffsetNumber off); int len, OffsetNumber off);
extern bool gistnospace(Page page, IndexTuple *itvec, int len);
extern IndexTuple *gistextractbuffer(Buffer buffer, int *len /* out */ ); extern IndexTuple *gistextractbuffer(Buffer buffer, int *len /* out */ );
extern IndexTuple *gistjoinvector( extern IndexTuple *gistjoinvector(
IndexTuple *itvec, int *len, IndexTuple *itvec, int *len,
......
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