|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * 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 $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -189,27 +189,39 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
|
189 | 189 | BlockNumbernblkno;
|
190 | 190 |
|
191 | 191 | /*
|
192 |
| - * make sure the offset points to an actualkey before trying to |
193 |
| - *compare it... |
| 192 | + * make sure the offset points to an actualitem before trying to |
| 193 | + *examine it... |
194 | 194 | */
|
195 | 195 | if (offset <=maxoff)
|
196 | 196 | {
|
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 |
| - |
206 | 197 | curitemid=PageGetItemId(page,offset);
|
207 | 198 |
|
208 | 199 | /*
|
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. |
210 | 212 | */
|
211 | 213 | if (!ItemIdDeleted(curitemid))
|
212 | 214 | {
|
| 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 ... */ |
213 | 225 | cbti= (BTItem)PageGetItem(page,curitemid);
|
214 | 226 | htup.t_self=cbti->bti_itup.t_tid;
|
215 | 227 | if (heap_fetch(heapRel,SnapshotDirty,&htup,&hbuffer,
|
@@ -1547,7 +1559,7 @@ _bt_pgaddtup(Relation rel,
|
1547 | 1559 | * _bt_isequal - used in _bt_doinsert in check for duplicates.
|
1548 | 1560 | *
|
1549 | 1561 | * This is very similar to _bt_compare, except for NULL handling.
|
1550 |
| - * Rule is simple: NOT_NULL not equal NULL, NULLnot_equal NULL too. |
| 1562 | + * Rule is simple: NOT_NULL not equal NULL, NULLnot equal NULL too. |
1551 | 1563 | */
|
1552 | 1564 | staticbool
|
1553 | 1565 | _bt_isequal(TupleDescitupdesc,Pagepage,OffsetNumberoffnum,
|
@@ -1576,7 +1588,7 @@ _bt_isequal(TupleDesc itupdesc, Page page, OffsetNumber offnum,
|
1576 | 1588 | datum=index_getattr(itup,attno,itupdesc,&isNull);
|
1577 | 1589 |
|
1578 | 1590 | /* NULLs are never equal to anything */
|
1579 |
| -if (entry->sk_flags&SK_ISNULL||isNull) |
| 1591 | +if ((entry->sk_flags&SK_ISNULL)||isNull) |
1580 | 1592 | return false;
|
1581 | 1593 |
|
1582 | 1594 | result=DatumGetInt32(FunctionCall2(&entry->sk_func,
|
|