Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 08ae5ed

Browse files
committed
Optimize the case where a btree indexscan has current and mark positions
on the same index page; we can avoid data copying as well as buffer refcount manipulations in this common case. Makes for a small but noticeable improvement in mergejoin speed. Heikki Linnakangas
1 parent 7ad642d commit 08ae5ed

File tree

3 files changed

+67
-26
lines changed

3 files changed

+67
-26
lines changed

src/backend/access/nbtree/nbtree.c

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* Portions Copyright (c) 1994, Regents of the University of California
1313
*
1414
* IDENTIFICATION
15-
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.149 2006/05/10 23:18:39 tgl Exp $
15+
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.150 2006/08/24 01:18:34 tgl Exp $
1616
*
1717
*-------------------------------------------------------------------------
1818
*/
@@ -392,6 +392,7 @@ btrescan(PG_FUNCTION_ARGS)
392392
ReleaseBuffer(so->markPos.buf);
393393
so->markPos.buf = InvalidBuffer;
394394
}
395+
so->markItemIndex = -1;
395396

396397
/*
397398
* Reset the scan keys. Note that keys ordering stuff moved to _bt_first.
@@ -430,6 +431,7 @@ btendscan(PG_FUNCTION_ARGS)
430431
ReleaseBuffer(so->markPos.buf);
431432
so->markPos.buf = InvalidBuffer;
432433
}
434+
so->markItemIndex = -1;
433435

434436
if (so->killedItems != NULL)
435437
pfree(so->killedItems);
@@ -456,14 +458,16 @@ btmarkpos(PG_FUNCTION_ARGS)
456458
so->markPos.buf = InvalidBuffer;
457459
}
458460

459-
/* bump pin on current buffer for assignment to mark buffer */
461+
/*
462+
* Just record the current itemIndex. If we later step to next page
463+
* before releasing the marked position, _bt_steppage makes a full copy
464+
* of the currPos struct in markPos. If (as often happens) the mark is
465+
* moved before we leave the page, we don't have to do that work.
466+
*/
460467
if (BTScanPosIsValid(so->currPos))
461-
{
462-
IncrBufferRefCount(so->currPos.buf);
463-
memcpy(&so->markPos, &so->currPos,
464-
offsetof(BTScanPosData, items[1]) +
465-
so->currPos.lastItem * sizeof(BTScanPosItem));
466-
}
468+
so->markItemIndex = so->currPos.itemIndex;
469+
else
470+
so->markItemIndex = -1;
467471

468472
PG_RETURN_VOID();
469473
}
@@ -477,24 +481,35 @@ btrestrpos(PG_FUNCTION_ARGS)
477481
IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
478482
BTScanOpaque so = (BTScanOpaque) scan->opaque;
479483

480-
/* we aren't holding any read locks, but gotta drop the pin */
481-
if (BTScanPosIsValid(so->currPos))
484+
if (so->markItemIndex >= 0)
482485
{
483-
/* Before leaving current page, deal with any killed items */
484-
if (so->numKilled > 0 &&
485-
so->currPos.buf != so->markPos.buf)
486-
_bt_killitems(scan, false);
487-
ReleaseBuffer(so->currPos.buf);
488-
so->currPos.buf = InvalidBuffer;
489-
}
490-
491-
/* bump pin on marked buffer */
492-
if (BTScanPosIsValid(so->markPos))
486+
/*
487+
* The mark position is on the same page we are currently on.
488+
* Just restore the itemIndex.
489+
*/
490+
so->currPos.itemIndex = so->markItemIndex;
491+
}
492+
else
493493
{
494-
IncrBufferRefCount(so->markPos.buf);
495-
memcpy(&so->currPos, &so->markPos,
496-
offsetof(BTScanPosData, items[1]) +
497-
so->markPos.lastItem * sizeof(BTScanPosItem));
494+
/* we aren't holding any read locks, but gotta drop the pin */
495+
if (BTScanPosIsValid(so->currPos))
496+
{
497+
/* Before leaving current page, deal with any killed items */
498+
if (so->numKilled > 0 &&
499+
so->currPos.buf != so->markPos.buf)
500+
_bt_killitems(scan, false);
501+
ReleaseBuffer(so->currPos.buf);
502+
so->currPos.buf = InvalidBuffer;
503+
}
504+
505+
if (BTScanPosIsValid(so->markPos))
506+
{
507+
/* bump pin on mark buffer for assignment to current buffer */
508+
IncrBufferRefCount(so->markPos.buf);
509+
memcpy(&so->currPos, &so->markPos,
510+
offsetof(BTScanPosData, items[1]) +
511+
so->markPos.lastItem * sizeof(BTScanPosItem));
512+
}
498513
}
499514

500515
PG_RETURN_VOID();

src/backend/access/nbtree/nbtsearch.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.105 2006/05/07 01:21:30 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.106 2006/08/24 01:18:34 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -815,6 +815,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
815815
so->currPos.moreRight = false;
816816
}
817817
so->numKilled = 0; /* just paranoia */
818+
so->markItemIndex = -1; /* ditto */
818819

819820
/* position to the precise item on the page */
820821
offnum = _bt_binsrch(rel, buf, keysCount, scankeys, nextkey);
@@ -1053,6 +1054,21 @@ _bt_steppage(IndexScanDesc scan, ScanDirection dir)
10531054
if (so->numKilled > 0)
10541055
_bt_killitems(scan, true);
10551056

1057+
/*
1058+
* Before we modify currPos, make a copy of the page data if there
1059+
* was a mark position that needs it.
1060+
*/
1061+
if (so->markItemIndex >= 0)
1062+
{
1063+
/* bump pin on current buffer for assignment to mark buffer */
1064+
IncrBufferRefCount(so->currPos.buf);
1065+
memcpy(&so->markPos, &so->currPos,
1066+
offsetof(BTScanPosData, items[1]) +
1067+
so->currPos.lastItem * sizeof(BTScanPosItem));
1068+
so->markPos.itemIndex = so->markItemIndex;
1069+
so->markItemIndex = -1;
1070+
}
1071+
10561072
rel = scan->indexRelation;
10571073

10581074
if (ScanDirectionIsForward(dir))
@@ -1408,6 +1424,7 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
14081424
so->currPos.moreRight = false;
14091425
}
14101426
so->numKilled = 0; /* just paranoia */
1427+
so->markItemIndex = -1; /* ditto */
14111428

14121429
/*
14131430
* Now load data from the first page of the scan.

src/include/access/nbtree.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.103 2006/08/07 16:57:57 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.104 2006/08/24 01:18:34 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -438,6 +438,15 @@ typedef struct BTScanOpaqueData
438438
int *killedItems; /* currPos.items indexes of killed items */
439439
int numKilled; /* number of currently stored items */
440440

441+
/*
442+
* If the marked position is on the same page as current position,
443+
* we don't use markPos, but just keep the marked itemIndex in
444+
* markItemIndex (all the rest of currPos is valid for the mark position).
445+
* Hence, to determine if there is a mark, first look at markItemIndex,
446+
* then at markPos.
447+
*/
448+
int markItemIndex; /* itemIndex, or -1 if not valid */
449+
441450
/* keep these last in struct for efficiency */
442451
BTScanPosData currPos; /* current position data */
443452
BTScanPosData markPos; /* marked position, if any */

0 commit comments

Comments
 (0)