diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c index 54ac45ee2f..326e87e788 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.137 2006/05/24 11:01:39 teodor Exp $ + * $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.138 2006/05/29 12:50:06 teodor Exp $ * *------------------------------------------------------------------------- */ @@ -1033,7 +1033,13 @@ gistSplitByKey(Relation r, Page page, IndexTuple *itup, int len, GISTSTATE *gist /* * all keys are not-null */ - gistUserPicksplit(r, entryvec, attno, v, itup, len, giststate); + if ( gistUserPicksplit(r, entryvec, attno, v, itup, len, giststate) && attno+1 != r->rd_att->natts ) + /* + * Splitting on attno column is not optimized: unions of left and right + * page are the same, we will try to split page by + * following columns + */ + gistSplitByKey(r, page, itup, len, giststate, v, entryvec, attno+1); } } diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c index 3db72aa199..987aed89f7 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.14 2006/05/24 11:01:39 teodor Exp $ + * $PostgreSQL: pgsql/src/backend/access/gist/gistutil.c,v 1.15 2006/05/29 12:50:06 teodor Exp $ *------------------------------------------------------------------------- */ #include "postgres.h" @@ -262,6 +262,16 @@ gistMakeUnionKey( GISTSTATE *giststate, int attno, } } +static bool +gistKeyIsEQ(GISTSTATE *giststate, int attno, Datum a, Datum b) { + bool result; + + FunctionCall3(&giststate->equalFn[attno], + a, b, + PointerGetDatum(&result)); + return result; +} + /* * Forms union of oldtup and addtup, if union == oldtup then return NULL */ @@ -300,19 +310,8 @@ gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *gis continue; if ( !addisnull[i] ) { - if ( oldisnull[i] ) + if ( oldisnull[i] || gistKeyIsEQ(giststate, i, oldentries[i].key, attrS[i])==false ) neednew = true; - else { - bool result; - - FunctionCall3(&giststate->equalFn[i], - oldentries[i].key, - attrS[i], - PointerGetDatum(&result)); - - if (!result) - neednew = true; - } } } @@ -395,7 +394,6 @@ gistfindgroup(GISTSTATE *giststate, GISTENTRY *valvec, GIST_SPLITVEC *spl, int a { int j; int len; - bool result; if (spl->spl_idgrp[spl->spl_left[i]]) continue; @@ -405,11 +403,7 @@ gistfindgroup(GISTSTATE *giststate, GISTENTRY *valvec, GIST_SPLITVEC *spl, int a { if (spl->spl_idgrp[spl->spl_right[j]]) continue; - FunctionCall3(&giststate->equalFn[attno], - valvec[spl->spl_left[i]].key, - valvec[spl->spl_right[j]].key, - PointerGetDatum(&result)); - if (result) + if (gistKeyIsEQ(giststate, attno, valvec[spl->spl_left[i]].key, valvec[spl->spl_right[j]].key)) { spl->spl_idgrp[spl->spl_right[j]] = curid; len++; @@ -425,11 +419,7 @@ gistfindgroup(GISTSTATE *giststate, GISTENTRY *valvec, GIST_SPLITVEC *spl, int a { if (spl->spl_idgrp[spl->spl_left[j]]) continue; - FunctionCall3(&giststate->equalFn[attno], - valvec[spl->spl_left[i]].key, - valvec[spl->spl_left[j]].key, - PointerGetDatum(&result)); - if (result) + if (gistKeyIsEQ(giststate, attno, valvec[spl->spl_left[i]].key, valvec[spl->spl_left[j]].key)) { spl->spl_idgrp[spl->spl_left[j]] = curid; len++; @@ -758,7 +748,14 @@ gistpenalty(GISTSTATE *giststate, int attno, return penalty; } -void +/* + * Calls user picksplit method for attno columns to split vector to + * two vectors. May use attno+n columns data to + * get better split. + * Returns TRUE if left and right unions of attno columns are the same, + * so caller may find better split + */ +bool gistUserPicksplit(Relation r, GistEntryVector *entryvec, int attno, GIST_SPLITVEC *v, IndexTuple *itup, int len, GISTSTATE *giststate) { @@ -787,24 +784,36 @@ gistUserPicksplit(Relation r, GistEntryVector *entryvec, int attno, GIST_SPLITVE */ if (giststate->tupdesc->natts > 1 && attno+1 != giststate->tupdesc->natts) { - int MaxGrpId; + if ( gistKeyIsEQ(giststate, attno, v->spl_ldatum, v->spl_rdatum) ) { + /* + * Left and right key's unions are equial, so + * we can get better split by following columns. Note, + * uninons for attno columns are already done. + */ - v->spl_idgrp = (int *) palloc0(sizeof(int) * entryvec->n); - v->spl_grpflag = (char *) palloc0(sizeof(char) * entryvec->n); - v->spl_ngrp = (int *) palloc(sizeof(int) * entryvec->n); + return true; + } else { + int MaxGrpId; - MaxGrpId = gistfindgroup(giststate, entryvec->vector, v, attno); + v->spl_idgrp = (int *) palloc0(sizeof(int) * entryvec->n); + v->spl_grpflag = (char *) palloc0(sizeof(char) * entryvec->n); + v->spl_ngrp = (int *) palloc(sizeof(int) * entryvec->n); - /* form union of sub keys for each page (l,p) */ - gistunionsubkey(giststate, itup, v, attno + 1); + MaxGrpId = gistfindgroup(giststate, entryvec->vector, v, attno); - /* - * if possible, we insert equivalent tuples with control by penalty - * for a subkey(s) - */ - if (MaxGrpId > 1) - gistadjsubkey(r, itup, len, v, giststate, attno); + /* form union of sub keys for each page (l,p) */ + gistunionsubkey(giststate, itup, v, attno + 1); + + /* + * if possible, we insert equivalent tuples with control by penalty + * for a subkey(s) + */ + if (MaxGrpId > 1) + gistadjsubkey(r, itup, len, v, giststate, attno); + } } + + return false; } /* diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h index 43a6f62943..f75682847a 100644 --- a/src/include/access/gist_private.h +++ b/src/include/access/gist_private.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/gist_private.h,v 1.16 2006/05/24 11:01:39 teodor Exp $ + * $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.17 2006/05/29 12:50:06 teodor Exp $ * *------------------------------------------------------------------------- */ @@ -312,7 +312,7 @@ extern void GISTInitBuffer(Buffer b, uint32 f); extern void gistdentryinit(GISTSTATE *giststate, int nkey, GISTENTRY *e, Datum k, Relation r, Page pg, OffsetNumber o, int b, bool l, bool isNull); -void gistUserPicksplit(Relation r, GistEntryVector *entryvec, int attno, GIST_SPLITVEC *v, +bool gistUserPicksplit(Relation r, GistEntryVector *entryvec, int attno, GIST_SPLITVEC *v, IndexTuple *itup, int len, GISTSTATE *giststate); /* gistvacuum.c */