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

Commit 5ac2d7c

Browse files
committed
In _bt_check_unique() loop, don't bother applying _bt_isequal() to
killed items; just skip to the next item immediately. Only check for key equality when we reach a non-killed item or the end of the index page. This saves key comparisons when there are lots of killed items, as for example in a heavily-updated table that's not been vacuumed lately. Seems to be a win for pgbench anyway.
1 parent 30b4abf commit 5ac2d7c

File tree

1 file changed

+27
-15
lines changed

1 file changed

+27
-15
lines changed

src/backend/access/nbtree/nbtinsert.c

Lines changed: 27 additions & 15 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.104 2003/08/04 02:39:57 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.105 2003/09/02 22:10:16 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -189,27 +189,39 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
189189
BlockNumber nblkno;
190190

191191
/*
192-
* make sure the offset points to an actual key before trying to
193-
* compare it...
192+
* make sure the offset points to an actual item before trying to
193+
* examine it...
194194
*/
195195
if (offset <= maxoff)
196196
{
197-
/*
198-
* _bt_compare returns 0 for (1,NULL) and (1,NULL) - this's
199-
* how we handling NULLs - and so we must not use _bt_compare
200-
* in real comparison, but only for ordering/finding items on
201-
* pages. - vadim 03/24/97
202-
*/
203-
if (!_bt_isequal(itupdesc, page, offset, natts, itup_scankey))
204-
break; /* we're past all the equal tuples */
205-
206197
curitemid = PageGetItemId(page, offset);
207198

208199
/*
209-
* We can skip the heap fetch if the item is marked killed.
200+
* We can skip items that are marked killed.
201+
*
202+
* Formerly, we applied _bt_isequal() before checking the kill
203+
* flag, so as to fall out of the item loop as soon as possible.
204+
* However, in the presence of heavy update activity an index
205+
* may contain many killed items with the same key; running
206+
* _bt_isequal() on each killed item gets expensive. Furthermore
207+
* it is likely that the non-killed version of each key appears
208+
* first, so that we didn't actually get to exit any sooner anyway.
209+
* So now we just advance over killed items as quickly as we can.
210+
* We only apply _bt_isequal() when we get to a non-killed item or
211+
* the end of the page.
210212
*/
211213
if (!ItemIdDeleted(curitemid))
212214
{
215+
/*
216+
* _bt_compare returns 0 for (1,NULL) and (1,NULL) - this's
217+
* how we handling NULLs - and so we must not use _bt_compare
218+
* in real comparison, but only for ordering/finding items on
219+
* pages. - vadim 03/24/97
220+
*/
221+
if (!_bt_isequal(itupdesc, page, offset, natts, itup_scankey))
222+
break; /* we're past all the equal tuples */
223+
224+
/* okay, we gotta fetch the heap tuple ... */
213225
cbti = (BTItem) PageGetItem(page, curitemid);
214226
htup.t_self = cbti->bti_itup.t_tid;
215227
if (heap_fetch(heapRel, SnapshotDirty, &htup, &hbuffer,
@@ -1547,7 +1559,7 @@ _bt_pgaddtup(Relation rel,
15471559
* _bt_isequal - used in _bt_doinsert in check for duplicates.
15481560
*
15491561
* This is very similar to _bt_compare, except for NULL handling.
1550-
* Rule is simple: NOT_NULL not equal NULL, NULL not_equal NULL too.
1562+
* Rule is simple: NOT_NULL not equal NULL, NULL not equal NULL too.
15511563
*/
15521564
static bool
15531565
_bt_isequal(TupleDesc itupdesc, Page page, OffsetNumber offnum,
@@ -1576,7 +1588,7 @@ _bt_isequal(TupleDesc itupdesc, Page page, OffsetNumber offnum,
15761588
datum = index_getattr(itup, attno, itupdesc, &isNull);
15771589

15781590
/* NULLs are never equal to anything */
1579-
if (entry->sk_flags & SK_ISNULL || isNull)
1591+
if ((entry->sk_flags & SK_ISNULL) || isNull)
15801592
return false;
15811593

15821594
result = DatumGetInt32(FunctionCall2(&entry->sk_func,

0 commit comments

Comments
 (0)