Skip to content

Commit 8cb6242

Browse files
committed
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.
1 parent 4935369 commit 8cb6242

File tree

7 files changed

+265
-287
lines changed

7 files changed

+265
-287
lines changed

src/backend/access/nbtree/nbtinsert.c

Lines changed: 101 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.54 2000/01/26 05:55:58 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.55 2000/02/18 06:32:33 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -20,8 +20,11 @@
2020

2121

2222
static InsertIndexResult _bt_insertonpg(Relation rel, Buffer buf, BTStack stack, int keysz, ScanKey scankey, BTItem btitem, BTItem afteritem);
23-
static Buffer _bt_split(Relation rel, Buffer buf, OffsetNumber firstright);
24-
static OffsetNumber _bt_findsplitloc(Relation rel, Page page, OffsetNumber start, OffsetNumber maxoff, Size llimit);
23+
static Buffer _bt_split(Relation rel, Size keysz, ScanKey scankey,
24+
Buffer buf, OffsetNumber firstright);
25+
static OffsetNumber _bt_findsplitloc(Relation rel, Size keysz, ScanKey scankey,
26+
Page page, OffsetNumber start,
27+
OffsetNumber maxoff, Size llimit);
2528
static void _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf);
2629
static OffsetNumber _bt_pgaddtup(Relation rel, Buffer buf, int keysz, ScanKey itup_scankey, Size itemsize, BTItem btitem, BTItem afteritem);
2730
static bool _bt_goesonpg(Relation rel, Buffer buf, Size keysz, ScanKey scankey, BTItem afteritem);
@@ -297,7 +300,7 @@ _bt_insertonpg(Relation rel,
297300
hitemid = PageGetItemId(page, P_HIKEY);
298301
hitem = (BTItem) PageGetItem(page, hitemid);
299302
if (maxoff > P_HIKEY &&
300-
!_bt_itemcmp(rel, keysz, hitem,
303+
!_bt_itemcmp(rel, keysz, scankey, hitem,
301304
(BTItem) PageGetItem(page, PageGetItemId(page, P_FIRSTKEY)),
302305
BTEqualStrategyNumber))
303306
elog(FATAL, "btree: bad key on the page in the chain of duplicates");
@@ -373,7 +376,8 @@ _bt_insertonpg(Relation rel,
373376
{
374377
itid = PageGetItemId(page, offnum);
375378
chkitem = (BTItem) PageGetItem(page, itid);
376-
if (!_bt_itemcmp(rel, keysz, previtem, chkitem,
379+
if (!_bt_itemcmp(rel, keysz, scankey,
380+
previtem, chkitem,
377381
BTEqualStrategyNumber))
378382
{
379383
if (currsize > maxsize)
@@ -471,9 +475,10 @@ _bt_insertonpg(Relation rel,
471475
MAXALIGN(sizeof(BTPageOpaqueData))
472476
+sizeof(ItemIdData);
473477
llimit /= 2;
474-
firstright = _bt_findsplitloc(rel, page, start, maxoff, llimit);
478+
firstright = _bt_findsplitloc(rel, keysz, scankey,
479+
page, start, maxoff, llimit);
475480

476-
if (_bt_itemcmp(rel, keysz,
481+
if (_bt_itemcmp(rel, keysz, scankey,
477482
(BTItem) PageGetItem(page, PageGetItemId(page, start)),
478483
(BTItem) PageGetItem(page, PageGetItemId(page, firstright)),
479484
BTEqualStrategyNumber))
@@ -503,7 +508,8 @@ _bt_insertonpg(Relation rel,
503508
ItemPointerSet(&(stack->bts_btitem->bti_itup.t_tid),
504509
bknum, P_HIKEY);
505510
pbuf = _bt_getstackbuf(rel, stack, BT_WRITE);
506-
if (_bt_itemcmp(rel, keysz, stack->bts_btitem,
511+
if (_bt_itemcmp(rel, keysz, scankey,
512+
stack->bts_btitem,
507513
(BTItem) PageGetItem(page,
508514
PageGetItemId(page, start)),
509515
BTLessStrategyNumber))
@@ -519,7 +525,7 @@ _bt_insertonpg(Relation rel,
519525
}
520526

521527
/* split the buffer into left and right halves */
522-
rbuf = _bt_split(rel, buf, firstright);
528+
rbuf = _bt_split(rel, keysz, scankey, buf, firstright);
523529

524530
/* which new page (left half or right half) gets the tuple? */
525531
if (_bt_goesonpg(rel, buf, keysz, scankey, afteritem))
@@ -550,7 +556,7 @@ _bt_insertonpg(Relation rel,
550556
elog(FATAL, "btree: un-shifted page is empty");
551557
lowLeftItem = (BTItem) PageGetItem(page,
552558
PageGetItemId(page, P_FIRSTKEY));
553-
if (_bt_itemcmp(rel, keysz, lowLeftItem,
559+
if (_bt_itemcmp(rel, keysz, scankey, lowLeftItem,
554560
(BTItem) PageGetItem(page, PageGetItemId(page, P_HIKEY)),
555561
BTEqualStrategyNumber))
556562
lpageop->btpo_flags |= BTP_CHAIN;
@@ -613,7 +619,8 @@ l_spl: ;
613619
{
614620
ritem = (BTItem) PageGetItem(rpage,
615621
PageGetItemId(rpage, P_FIRSTKEY));
616-
if (_bt_itemcmp(rel, keysz, ritem,
622+
if (_bt_itemcmp(rel, keysz, scankey,
623+
ritem,
617624
(BTItem) PageGetItem(rpage,
618625
PageGetItemId(rpage, P_HIKEY)),
619626
BTEqualStrategyNumber))
@@ -663,13 +670,16 @@ l_spl: ;
663670
* possible in splitting leftmost page) and current parent
664671
* item == new_item. - vadim 05/27/97
665672
*/
666-
if (_bt_itemcmp(rel, keysz, stack->bts_btitem, new_item,
673+
if (_bt_itemcmp(rel, keysz, scankey,
674+
stack->bts_btitem, new_item,
667675
BTGreaterStrategyNumber) ||
668676
(!shifted &&
669-
_bt_itemcmp(rel, keysz, stack->bts_btitem,
670-
new_item, BTEqualStrategyNumber) &&
671-
_bt_itemcmp(rel, keysz, lowLeftItem,
672-
new_item, BTLessStrategyNumber)))
677+
_bt_itemcmp(rel, keysz, scankey,
678+
stack->bts_btitem, new_item,
679+
BTEqualStrategyNumber) &&
680+
_bt_itemcmp(rel, keysz, scankey,
681+
lowLeftItem, new_item,
682+
BTLessStrategyNumber)))
673683
{
674684
do_update = true;
675685

@@ -831,7 +841,8 @@ l_spl: ;
831841
* pin and lock on buf are maintained.
832842
*/
833843
static Buffer
834-
_bt_split(Relation rel, Buffer buf, OffsetNumber firstright)
844+
_bt_split(Relation rel, Size keysz, ScanKey scankey,
845+
Buffer buf, OffsetNumber firstright)
835846
{
836847
Buffer rbuf;
837848
Page origpage;
@@ -915,7 +926,8 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright)
915926
{
916927
Size llimit = PageGetFreeSpace(leftpage) / 2;
917928

918-
firstright = _bt_findsplitloc(rel, origpage, start, maxoff, llimit);
929+
firstright = _bt_findsplitloc(rel, keysz, scankey,
930+
origpage, start, maxoff, llimit);
919931
}
920932

921933
for (i = start; i <= maxoff; i = OffsetNumberNext(i))
@@ -1027,6 +1039,8 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright)
10271039
*/
10281040
static OffsetNumber
10291041
_bt_findsplitloc(Relation rel,
1042+
Size keysz,
1043+
ScanKey scankey,
10301044
Page page,
10311045
OffsetNumber start,
10321046
OffsetNumber maxoff,
@@ -1039,12 +1053,10 @@ _bt_findsplitloc(Relation rel,
10391053
BTItem safeitem,
10401054
nxtitem;
10411055
Size nbytes;
1042-
int natts;
10431056

10441057
if (start >= maxoff)
10451058
elog(FATAL, "btree: cannot split if start (%d) >= maxoff (%d)",
10461059
start, maxoff);
1047-
natts = rel->rd_rel->relnatts;
10481060
saferight = start;
10491061
safeitemid = PageGetItemId(page, saferight);
10501062
nbytes = ItemIdGetLength(safeitemid) + sizeof(ItemIdData);
@@ -1064,7 +1076,7 @@ _bt_findsplitloc(Relation rel,
10641076
* at isn't equal to the last safe one we saw, then it's our new
10651077
* safe tuple.
10661078
*/
1067-
if (!_bt_itemcmp(rel, natts,
1079+
if (!_bt_itemcmp(rel, keysz, scankey,
10681080
safeitem, nxtitem, BTEqualStrategyNumber))
10691081
{
10701082
safeitem = nxtitem;
@@ -1345,92 +1357,94 @@ _bt_goesonpg(Relation rel,
13451357
}
13461358

13471359
/*
1348-
* _bt_itemcmp() -- compare item1 to item2 using a requested
1349-
* strategy (<, <=, =, >=, >)
1360+
* _bt_tuplecompare() -- compare two IndexTuples,
1361+
* return -1, 0, or +1
13501362
*
13511363
*/
1352-
bool
1353-
_bt_itemcmp(Relation rel,
1354-
Size keysz,
1355-
BTItem item1,
1356-
BTItem item2,
1357-
StrategyNumber strat)
1364+
int32
1365+
_bt_tuplecompare(Relation rel,
1366+
Size keysz,
1367+
ScanKey scankey,
1368+
IndexTuple tuple1,
1369+
IndexTuple tuple2)
13581370
{
13591371
TupleDesc tupDes;
1360-
IndexTuple indexTuple1,
1361-
indexTuple2;
1362-
Datum attrDatum1,
1363-
attrDatum2;
13641372
int i;
1365-
bool isFirstNull,
1366-
isSecondNull;
1367-
bool compare;
1368-
bool useEqual = false;
1369-
1370-
if (strat == BTLessEqualStrategyNumber)
1371-
{
1372-
useEqual = true;
1373-
strat = BTLessStrategyNumber;
1374-
}
1375-
else if (strat == BTGreaterEqualStrategyNumber)
1376-
{
1377-
useEqual = true;
1378-
strat = BTGreaterStrategyNumber;
1379-
}
1373+
int32 compare = 0;
13801374

13811375
tupDes = RelationGetDescr(rel);
1382-
indexTuple1 = &(item1->bti_itup);
1383-
indexTuple2 = &(item2->bti_itup);
13841376

13851377
for (i = 1; i <= keysz; i++)
13861378
{
1387-
attrDatum1 = index_getattr(indexTuple1, i, tupDes, &isFirstNull);
1388-
attrDatum2 = index_getattr(indexTuple2, i, tupDes, &isSecondNull);
1379+
ScanKey entry = &scankey[i - 1];
1380+
Datum attrDatum1,
1381+
attrDatum2;
1382+
bool isFirstNull,
1383+
isSecondNull;
1384+
1385+
attrDatum1 = index_getattr(tuple1, i, tupDes, &isFirstNull);
1386+
attrDatum2 = index_getattr(tuple2, i, tupDes, &isSecondNull);
13891387

13901388
/* see comments about NULLs handling in btbuild */
1391-
if (isFirstNull) /* attr in item1 is NULL */
1389+
if (isFirstNull) /* attr in tuple1 is NULL */
13921390
{
1393-
if (isSecondNull) /* attr in item2 is NULL too */
1394-
compare = (strat == BTEqualStrategyNumber) ? true : false;
1391+
if (isSecondNull) /* attr in tuple2 is NULL too */
1392+
compare = 0;
13951393
else
1396-
compare = (strat == BTGreaterStrategyNumber) ? true : false;
1394+
compare = 1; /* NULL ">" not-NULL */
13971395
}
1398-
else if (isSecondNull) /* attr in item1 is NOT_NULL and */
1399-
{ /* and attr in item2 is NULL */
1400-
compare = (strat == BTLessStrategyNumber) ? true : false;
1396+
else if (isSecondNull) /* attr in tuple1 is NOT_NULL and */
1397+
{ /* attr in tuple2 is NULL */
1398+
compare = -1; /* not-NULL "<" NULL */
14011399
}
14021400
else
1403-
compare = _bt_invokestrat(rel, i, strat, attrDatum1, attrDatum2);
1404-
1405-
if (compare) /* true for one of ">, <, =" */
14061401
{
1407-
if (strat != BTEqualStrategyNumber)
1408-
return true;
1402+
compare = (int32) FMGR_PTR2(&entry->sk_func,
1403+
attrDatum1, attrDatum2);
14091404
}
1410-
else
1411-
/* false for one of ">, <, =" */
1412-
{
1413-
if (strat == BTEqualStrategyNumber)
1414-
return false;
14151405

1416-
/*
1417-
* if original strat was "<=, >=" OR "<, >" but some
1418-
* attribute(s) left - need to test for Equality
1419-
*/
1420-
if (useEqual || i < keysz)
1421-
{
1422-
if (isFirstNull || isSecondNull)
1423-
compare = (isFirstNull && isSecondNull) ? true : false;
1424-
else
1425-
compare = _bt_invokestrat(rel, i, BTEqualStrategyNumber,
1426-
attrDatum1, attrDatum2);
1427-
if (compare) /* item1' and item2' attributes are equal */
1428-
continue; /* - try to compare next attributes */
1429-
}
1430-
return false;
1431-
}
1406+
if (compare != 0)
1407+
break; /* done when we find unequal attributes */
14321408
}
1433-
return true;
1409+
1410+
return compare;
1411+
}
1412+
1413+
/*
1414+
* _bt_itemcmp() -- compare two BTItems using a requested
1415+
* strategy (<, <=, =, >=, >)
1416+
*
1417+
*/
1418+
bool
1419+
_bt_itemcmp(Relation rel,
1420+
Size keysz,
1421+
ScanKey scankey,
1422+
BTItem item1,
1423+
BTItem item2,
1424+
StrategyNumber strat)
1425+
{
1426+
int32 compare;
1427+
1428+
compare = _bt_tuplecompare(rel, keysz, scankey,
1429+
&(item1->bti_itup),
1430+
&(item2->bti_itup));
1431+
1432+
switch (strat)
1433+
{
1434+
case BTLessStrategyNumber:
1435+
return (bool) (compare < 0);
1436+
case BTLessEqualStrategyNumber:
1437+
return (bool) (compare <= 0);
1438+
case BTEqualStrategyNumber:
1439+
return (bool) (compare == 0);
1440+
case BTGreaterEqualStrategyNumber:
1441+
return (bool) (compare >= 0);
1442+
case BTGreaterStrategyNumber:
1443+
return (bool) (compare > 0);
1444+
}
1445+
1446+
elog(ERROR, "_bt_itemcmp: bogus strategy %d", (int) strat);
1447+
return false;
14341448
}
14351449

14361450
/*
@@ -1585,7 +1599,7 @@ _bt_shift(Relation rel, Buffer buf, BTStack stack, int keysz,
15851599
/* init old page opaque */
15861600
pageop->btpo_flags = npageop->btpo_flags; /* restore flags */
15871601
pageop->btpo_flags &= ~BTP_CHAIN;
1588-
if (_bt_itemcmp(rel, keysz, hikey, btitem, BTEqualStrategyNumber))
1602+
if (_bt_itemcmp(rel, keysz, scankey, hikey, btitem, BTEqualStrategyNumber))
15891603
pageop->btpo_flags |= BTP_CHAIN;
15901604
pageop->btpo_prev = npageop->btpo_prev; /* restore prev */
15911605
pageop->btpo_next = nbknum; /* next points to the new page */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy