1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-03 09:13:20 +03:00

Replace inefficient _bt_invokestrat calls with direct calls to the

appropriate btree three-way comparison routine.  Not clear why the
three-way comparison routines were being used in some paths and not
others in btree --- incomplete changes by someone long ago, maybe?
Anyway, this makes for a nice speedup in CREATE INDEX.
This commit is contained in:
Tom Lane
2000-02-18 06:32:39 +00:00
parent 49353692d1
commit 8cb624262a
7 changed files with 272 additions and 294 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.54 2000/01/26 05:55:58 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.55 2000/02/18 06:32:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,8 +20,11 @@
static InsertIndexResult _bt_insertonpg(Relation rel, Buffer buf, BTStack stack, int keysz, ScanKey scankey, BTItem btitem, BTItem afteritem);
static Buffer _bt_split(Relation rel, Buffer buf, OffsetNumber firstright);
static OffsetNumber _bt_findsplitloc(Relation rel, Page page, OffsetNumber start, OffsetNumber maxoff, Size llimit);
static Buffer _bt_split(Relation rel, Size keysz, ScanKey scankey,
Buffer buf, OffsetNumber firstright);
static OffsetNumber _bt_findsplitloc(Relation rel, Size keysz, ScanKey scankey,
Page page, OffsetNumber start,
OffsetNumber maxoff, Size llimit);
static void _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf);
static OffsetNumber _bt_pgaddtup(Relation rel, Buffer buf, int keysz, ScanKey itup_scankey, Size itemsize, BTItem btitem, BTItem afteritem);
static bool _bt_goesonpg(Relation rel, Buffer buf, Size keysz, ScanKey scankey, BTItem afteritem);
@@ -297,7 +300,7 @@ _bt_insertonpg(Relation rel,
hitemid = PageGetItemId(page, P_HIKEY);
hitem = (BTItem) PageGetItem(page, hitemid);
if (maxoff > P_HIKEY &&
!_bt_itemcmp(rel, keysz, hitem,
!_bt_itemcmp(rel, keysz, scankey, hitem,
(BTItem) PageGetItem(page, PageGetItemId(page, P_FIRSTKEY)),
BTEqualStrategyNumber))
elog(FATAL, "btree: bad key on the page in the chain of duplicates");
@@ -373,7 +376,8 @@ _bt_insertonpg(Relation rel,
{
itid = PageGetItemId(page, offnum);
chkitem = (BTItem) PageGetItem(page, itid);
if (!_bt_itemcmp(rel, keysz, previtem, chkitem,
if (!_bt_itemcmp(rel, keysz, scankey,
previtem, chkitem,
BTEqualStrategyNumber))
{
if (currsize > maxsize)
@@ -471,9 +475,10 @@ _bt_insertonpg(Relation rel,
MAXALIGN(sizeof(BTPageOpaqueData))
+sizeof(ItemIdData);
llimit /= 2;
firstright = _bt_findsplitloc(rel, page, start, maxoff, llimit);
firstright = _bt_findsplitloc(rel, keysz, scankey,
page, start, maxoff, llimit);
if (_bt_itemcmp(rel, keysz,
if (_bt_itemcmp(rel, keysz, scankey,
(BTItem) PageGetItem(page, PageGetItemId(page, start)),
(BTItem) PageGetItem(page, PageGetItemId(page, firstright)),
BTEqualStrategyNumber))
@@ -503,7 +508,8 @@ _bt_insertonpg(Relation rel,
ItemPointerSet(&(stack->bts_btitem->bti_itup.t_tid),
bknum, P_HIKEY);
pbuf = _bt_getstackbuf(rel, stack, BT_WRITE);
if (_bt_itemcmp(rel, keysz, stack->bts_btitem,
if (_bt_itemcmp(rel, keysz, scankey,
stack->bts_btitem,
(BTItem) PageGetItem(page,
PageGetItemId(page, start)),
BTLessStrategyNumber))
@@ -519,7 +525,7 @@ _bt_insertonpg(Relation rel,
}
/* split the buffer into left and right halves */
rbuf = _bt_split(rel, buf, firstright);
rbuf = _bt_split(rel, keysz, scankey, buf, firstright);
/* which new page (left half or right half) gets the tuple? */
if (_bt_goesonpg(rel, buf, keysz, scankey, afteritem))
@@ -550,7 +556,7 @@ _bt_insertonpg(Relation rel,
elog(FATAL, "btree: un-shifted page is empty");
lowLeftItem = (BTItem) PageGetItem(page,
PageGetItemId(page, P_FIRSTKEY));
if (_bt_itemcmp(rel, keysz, lowLeftItem,
if (_bt_itemcmp(rel, keysz, scankey, lowLeftItem,
(BTItem) PageGetItem(page, PageGetItemId(page, P_HIKEY)),
BTEqualStrategyNumber))
lpageop->btpo_flags |= BTP_CHAIN;
@@ -613,7 +619,8 @@ l_spl: ;
{
ritem = (BTItem) PageGetItem(rpage,
PageGetItemId(rpage, P_FIRSTKEY));
if (_bt_itemcmp(rel, keysz, ritem,
if (_bt_itemcmp(rel, keysz, scankey,
ritem,
(BTItem) PageGetItem(rpage,
PageGetItemId(rpage, P_HIKEY)),
BTEqualStrategyNumber))
@@ -663,13 +670,16 @@ l_spl: ;
* possible in splitting leftmost page) and current parent
* item == new_item. - vadim 05/27/97
*/
if (_bt_itemcmp(rel, keysz, stack->bts_btitem, new_item,
if (_bt_itemcmp(rel, keysz, scankey,
stack->bts_btitem, new_item,
BTGreaterStrategyNumber) ||
(!shifted &&
_bt_itemcmp(rel, keysz, stack->bts_btitem,
new_item, BTEqualStrategyNumber) &&
_bt_itemcmp(rel, keysz, lowLeftItem,
new_item, BTLessStrategyNumber)))
_bt_itemcmp(rel, keysz, scankey,
stack->bts_btitem, new_item,
BTEqualStrategyNumber) &&
_bt_itemcmp(rel, keysz, scankey,
lowLeftItem, new_item,
BTLessStrategyNumber)))
{
do_update = true;
@@ -831,7 +841,8 @@ l_spl: ;
* pin and lock on buf are maintained.
*/
static Buffer
_bt_split(Relation rel, Buffer buf, OffsetNumber firstright)
_bt_split(Relation rel, Size keysz, ScanKey scankey,
Buffer buf, OffsetNumber firstright)
{
Buffer rbuf;
Page origpage;
@@ -915,7 +926,8 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright)
{
Size llimit = PageGetFreeSpace(leftpage) / 2;
firstright = _bt_findsplitloc(rel, origpage, start, maxoff, llimit);
firstright = _bt_findsplitloc(rel, keysz, scankey,
origpage, start, maxoff, llimit);
}
for (i = start; i <= maxoff; i = OffsetNumberNext(i))
@@ -1027,6 +1039,8 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright)
*/
static OffsetNumber
_bt_findsplitloc(Relation rel,
Size keysz,
ScanKey scankey,
Page page,
OffsetNumber start,
OffsetNumber maxoff,
@@ -1039,12 +1053,10 @@ _bt_findsplitloc(Relation rel,
BTItem safeitem,
nxtitem;
Size nbytes;
int natts;
if (start >= maxoff)
elog(FATAL, "btree: cannot split if start (%d) >= maxoff (%d)",
start, maxoff);
natts = rel->rd_rel->relnatts;
saferight = start;
safeitemid = PageGetItemId(page, saferight);
nbytes = ItemIdGetLength(safeitemid) + sizeof(ItemIdData);
@@ -1064,7 +1076,7 @@ _bt_findsplitloc(Relation rel,
* at isn't equal to the last safe one we saw, then it's our new
* safe tuple.
*/
if (!_bt_itemcmp(rel, natts,
if (!_bt_itemcmp(rel, keysz, scankey,
safeitem, nxtitem, BTEqualStrategyNumber))
{
safeitem = nxtitem;
@@ -1345,92 +1357,94 @@ _bt_goesonpg(Relation rel,
}
/*
* _bt_itemcmp() -- compare item1 to item2 using a requested
* _bt_tuplecompare() -- compare two IndexTuples,
* return -1, 0, or +1
*
*/
int32
_bt_tuplecompare(Relation rel,
Size keysz,
ScanKey scankey,
IndexTuple tuple1,
IndexTuple tuple2)
{
TupleDesc tupDes;
int i;
int32 compare = 0;
tupDes = RelationGetDescr(rel);
for (i = 1; i <= keysz; i++)
{
ScanKey entry = &scankey[i - 1];
Datum attrDatum1,
attrDatum2;
bool isFirstNull,
isSecondNull;
attrDatum1 = index_getattr(tuple1, i, tupDes, &isFirstNull);
attrDatum2 = index_getattr(tuple2, i, tupDes, &isSecondNull);
/* see comments about NULLs handling in btbuild */
if (isFirstNull) /* attr in tuple1 is NULL */
{
if (isSecondNull) /* attr in tuple2 is NULL too */
compare = 0;
else
compare = 1; /* NULL ">" not-NULL */
}
else if (isSecondNull) /* attr in tuple1 is NOT_NULL and */
{ /* attr in tuple2 is NULL */
compare = -1; /* not-NULL "<" NULL */
}
else
{
compare = (int32) FMGR_PTR2(&entry->sk_func,
attrDatum1, attrDatum2);
}
if (compare != 0)
break; /* done when we find unequal attributes */
}
return compare;
}
/*
* _bt_itemcmp() -- compare two BTItems using a requested
* strategy (<, <=, =, >=, >)
*
*/
bool
_bt_itemcmp(Relation rel,
Size keysz,
ScanKey scankey,
BTItem item1,
BTItem item2,
StrategyNumber strat)
{
TupleDesc tupDes;
IndexTuple indexTuple1,
indexTuple2;
Datum attrDatum1,
attrDatum2;
int i;
bool isFirstNull,
isSecondNull;
bool compare;
bool useEqual = false;
int32 compare;
if (strat == BTLessEqualStrategyNumber)
compare = _bt_tuplecompare(rel, keysz, scankey,
&(item1->bti_itup),
&(item2->bti_itup));
switch (strat)
{
useEqual = true;
strat = BTLessStrategyNumber;
}
else if (strat == BTGreaterEqualStrategyNumber)
{
useEqual = true;
strat = BTGreaterStrategyNumber;
case BTLessStrategyNumber:
return (bool) (compare < 0);
case BTLessEqualStrategyNumber:
return (bool) (compare <= 0);
case BTEqualStrategyNumber:
return (bool) (compare == 0);
case BTGreaterEqualStrategyNumber:
return (bool) (compare >= 0);
case BTGreaterStrategyNumber:
return (bool) (compare > 0);
}
tupDes = RelationGetDescr(rel);
indexTuple1 = &(item1->bti_itup);
indexTuple2 = &(item2->bti_itup);
for (i = 1; i <= keysz; i++)
{
attrDatum1 = index_getattr(indexTuple1, i, tupDes, &isFirstNull);
attrDatum2 = index_getattr(indexTuple2, i, tupDes, &isSecondNull);
/* see comments about NULLs handling in btbuild */
if (isFirstNull) /* attr in item1 is NULL */
{
if (isSecondNull) /* attr in item2 is NULL too */
compare = (strat == BTEqualStrategyNumber) ? true : false;
else
compare = (strat == BTGreaterStrategyNumber) ? true : false;
}
else if (isSecondNull) /* attr in item1 is NOT_NULL and */
{ /* and attr in item2 is NULL */
compare = (strat == BTLessStrategyNumber) ? true : false;
}
else
compare = _bt_invokestrat(rel, i, strat, attrDatum1, attrDatum2);
if (compare) /* true for one of ">, <, =" */
{
if (strat != BTEqualStrategyNumber)
return true;
}
else
/* false for one of ">, <, =" */
{
if (strat == BTEqualStrategyNumber)
return false;
/*
* if original strat was "<=, >=" OR "<, >" but some
* attribute(s) left - need to test for Equality
*/
if (useEqual || i < keysz)
{
if (isFirstNull || isSecondNull)
compare = (isFirstNull && isSecondNull) ? true : false;
else
compare = _bt_invokestrat(rel, i, BTEqualStrategyNumber,
attrDatum1, attrDatum2);
if (compare) /* item1' and item2' attributes are equal */
continue; /* - try to compare next attributes */
}
return false;
}
}
return true;
elog(ERROR, "_bt_itemcmp: bogus strategy %d", (int) strat);
return false;
}
/*
@@ -1585,7 +1599,7 @@ _bt_shift(Relation rel, Buffer buf, BTStack stack, int keysz,
/* init old page opaque */
pageop->btpo_flags = npageop->btpo_flags; /* restore flags */
pageop->btpo_flags &= ~BTP_CHAIN;
if (_bt_itemcmp(rel, keysz, hikey, btitem, BTEqualStrategyNumber))
if (_bt_itemcmp(rel, keysz, scankey, hikey, btitem, BTEqualStrategyNumber))
pageop->btpo_flags |= BTP_CHAIN;
pageop->btpo_prev = npageop->btpo_prev; /* restore prev */
pageop->btpo_next = nbknum; /* next points to the new page */