Skip to content

Commit b0d5036

Browse files
author
Hiroshi Inoue
committed
CREATE btree INDEX takes dead tuples into account when old transactions
are running.
1 parent 5ab40f0 commit b0d5036

File tree

3 files changed

+162
-28
lines changed

3 files changed

+162
-28
lines changed

src/backend/access/nbtree/nbtree.c

Lines changed: 58 additions & 4 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-
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.62 2000/07/21 06:42:32 tgl Exp $
15+
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.63 2000/08/10 02:33:20 inoue Exp $
1616
*
1717
*-------------------------------------------------------------------------
1818
*/
@@ -25,6 +25,7 @@
2525
#include "catalog/index.h"
2626
#include "executor/executor.h"
2727
#include "miscadmin.h"
28+
#include "storage/sinval.h"
2829

2930

3031
bool BuildingBtree = false; /* see comment in btbuild() */
@@ -70,6 +71,16 @@ btbuild(PG_FUNCTION_ARGS)
7071
BTSpool *spool = NULL;
7172
BTItem btitem;
7273
bool usefast;
74+
Snapshot snapshot;
75+
TransactionId XmaxRecent;
76+
/*
77+
* spool2 is needed only when the index is an unique index.
78+
* Dead tuples are put into spool2 instead of spool in
79+
* order to avoid uniqueness check.
80+
*/
81+
BTSpool *spool2 = NULL;
82+
bool tupleIsAlive;
83+
int dead_count;
7384

7485
/* note that this is a new btree */
7586
BuildingBtree = true;
@@ -135,13 +146,41 @@ btbuild(PG_FUNCTION_ARGS)
135146
nhtups = nitups = 0;
136147

137148
if (usefast)
149+
{
138150
spool = _bt_spoolinit(index, indexInfo->ii_Unique);
151+
/*
152+
* Different from spool,the uniqueness isn't checked
153+
* for spool2.
154+
*/
155+
if (indexInfo->ii_Unique)
156+
spool2 = _bt_spoolinit(index, false);
157+
}
139158

140159
/* start a heap scan */
141-
hscan = heap_beginscan(heap, 0, SnapshotNow, 0, (ScanKey) NULL);
160+
dead_count = 0;
161+
snapshot = (IsBootstrapProcessingMode() ? SnapshotNow : SnapshotAny);
162+
hscan = heap_beginscan(heap, 0, snapshot, 0, (ScanKey) NULL);
163+
XmaxRecent = 0;
164+
if (snapshot == SnapshotAny)
165+
GetXmaxRecent(&XmaxRecent);
142166

143167
while (HeapTupleIsValid(htup = heap_getnext(hscan, 0)))
144168
{
169+
if (snapshot == SnapshotAny)
170+
{
171+
tupleIsAlive = HeapTupleSatisfiesNow(htup->t_data);
172+
if (!tupleIsAlive)
173+
{
174+
if ((htup->t_data->t_infomask & HEAP_XMIN_INVALID) != 0)
175+
continue;
176+
if (htup->t_data->t_infomask & HEAP_XMAX_COMMITTED &&
177+
htup->t_data->t_xmax < XmaxRecent)
178+
continue;
179+
}
180+
}
181+
else
182+
tupleIsAlive = true;
183+
145184
MemoryContextReset(econtext->ecxt_per_tuple_memory);
146185

147186
nhtups++;
@@ -222,7 +261,15 @@ btbuild(PG_FUNCTION_ARGS)
222261
* into the btree.
223262
*/
224263
if (usefast)
225-
_bt_spool(btitem, spool);
264+
{
265+
if (tupleIsAlive || !spool2)
266+
_bt_spool(btitem, spool);
267+
else /* dead tuples are put into spool2 */
268+
{
269+
dead_count++;
270+
_bt_spool(btitem, spool2);
271+
}
272+
}
226273
else
227274
res = _bt_doinsert(index, btitem, indexInfo->ii_Unique, heap);
228275

@@ -234,6 +281,11 @@ btbuild(PG_FUNCTION_ARGS)
234281

235282
/* okay, all heap tuples are indexed */
236283
heap_endscan(hscan);
284+
if (spool2 && !dead_count) /* spool2 was found to be unnecessary */
285+
{
286+
_bt_spooldestroy(spool2);
287+
spool2 = NULL;
288+
}
237289

238290
#ifndef OMIT_PARTIAL_INDEX
239291
if (pred != NULL || oldPred != NULL)
@@ -250,8 +302,10 @@ btbuild(PG_FUNCTION_ARGS)
250302
*/
251303
if (usefast)
252304
{
253-
_bt_leafbuild(spool);
305+
_bt_leafbuild(spool, spool2);
254306
_bt_spooldestroy(spool);
307+
if (spool2)
308+
_bt_spooldestroy(spool2);
255309
}
256310

257311
#ifdef BTREE_BUILD_STATS

src/backend/access/nbtree/nbtsort.c

Lines changed: 102 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
* Portions Copyright (c) 1994, Regents of the University of California
3636
*
3737
* IDENTIFICATION
38-
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsort.c,v 1.56 2000/07/21 22:14:09 tgl Exp $
38+
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsort.c,v 1.57 2000/08/10 02:33:20 inoue Exp $
3939
*
4040
*-------------------------------------------------------------------------
4141
*/
@@ -95,7 +95,7 @@ static void _bt_sortaddtup(Page page, Size itemsize,
9595
BTItem btitem, OffsetNumber itup_off);
9696
static void _bt_buildadd(Relation index, BTPageState *state, BTItem bti);
9797
static void _bt_uppershutdown(Relation index, BTPageState *state);
98-
static void _bt_load(Relation index, BTSpool *btspool);
98+
static void _bt_load(Relation index, BTSpool *btspool, BTSpool *btspool2);
9999

100100

101101
/*
@@ -153,7 +153,7 @@ _bt_spool(BTItem btitem, BTSpool *btspool)
153153
* create an entire btree.
154154
*/
155155
void
156-
_bt_leafbuild(BTSpool *btspool)
156+
_bt_leafbuild(BTSpool *btspool, BTSpool *btspool2)
157157
{
158158
#ifdef BTREE_BUILD_STATS
159159
if (Show_btree_build_stats)
@@ -165,7 +165,9 @@ _bt_leafbuild(BTSpool *btspool)
165165
#endif /* BTREE_BUILD_STATS */
166166
tuplesort_performsort(btspool->sortstate);
167167

168-
_bt_load(btspool->index, btspool);
168+
if (btspool2)
169+
tuplesort_performsort(btspool2->sortstate);
170+
_bt_load(btspool->index, btspool, btspool2);
169171
}
170172

171173

@@ -523,28 +525,106 @@ _bt_uppershutdown(Relation index, BTPageState *state)
523525
* btree leaves.
524526
*/
525527
static void
526-
_bt_load(Relation index, BTSpool *btspool)
528+
_bt_load(Relation index, BTSpool *btspool, BTSpool *btspool2)
527529
{
528530
BTPageState *state = NULL;
529-
530-
for (;;)
531+
bool merge = (btspool2 != NULL);
532+
BTItem bti, bti2 = NULL;
533+
bool should_free, should_free2, load1;
534+
TupleDesc tupdes = RelationGetDescr(index);
535+
int i, keysz = RelationGetNumberOfAttributes(index);
536+
ScanKey indexScanKey = NULL;
537+
538+
if (merge)
531539
{
532-
BTItem bti;
533-
bool should_free;
534-
535-
bti = (BTItem) tuplesort_getindextuple(btspool->sortstate, true,
536-
&should_free);
537-
if (bti == (BTItem) NULL)
538-
break;
539-
540-
/* When we see first tuple, create first index page */
541-
if (state == NULL)
542-
state = _bt_pagestate(index, BTP_LEAF, 0);
543-
544-
_bt_buildadd(index, state, bti);
540+
/*
541+
* Another BTSpool for dead tuples exists.
542+
* Now we have to merge btspool and btspool2.
543+
*/
544+
ScanKey entry;
545+
Datum attrDatum1, attrDatum2;
546+
bool isFirstNull, isSecondNull;
547+
int32 compare;
548+
549+
/* the preparation of merge */
550+
bti = (BTItem) tuplesort_getindextuple(btspool->sortstate, true, &should_free);
551+
bti2 = (BTItem) tuplesort_getindextuple(btspool2->sortstate, true, &should_free2);
552+
indexScanKey = _bt_mkscankey_nodata(index);
553+
for (;;)
554+
{
555+
load1 = true; /* load BTSpool next ? */
556+
if (NULL == bti2)
557+
{
558+
if (NULL == bti)
559+
break;
560+
}
561+
else if (NULL != bti)
562+
{
563+
564+
for (i = 1; i <= keysz; i++)
565+
{
566+
entry = indexScanKey + i - 1;
567+
attrDatum1 = index_getattr((IndexTuple)bti, i, tupdes, &isFirstNull);
568+
attrDatum2 = index_getattr((IndexTuple)bti2, i, tupdes, &isSecondNull);
569+
if (isFirstNull)
570+
{
571+
if (!isSecondNull)
572+
{
573+
load1 = false;
574+
break;
575+
}
576+
}
577+
else if (isSecondNull)
578+
break;
579+
else
580+
{
581+
compare = DatumGetInt32(FunctionCall2(&entry->sk_func, attrDatum1, attrDatum2));
582+
if (compare > 0)
583+
{
584+
load1 = false;
585+
break;
586+
}
587+
else if (compare < 0)
588+
break;
589+
}
590+
}
591+
}
592+
else
593+
load1 = false;
594+
595+
/* When we see first tuple, create first index page */
596+
if (state == NULL)
597+
state = _bt_pagestate(index, BTP_LEAF, 0);
598+
599+
if (load1)
600+
{
601+
_bt_buildadd(index, state, bti);
602+
if (should_free)
603+
pfree((void *) bti);
604+
bti = (BTItem) tuplesort_getindextuple(btspool->sortstate, true, &should_free);
605+
}
606+
else
607+
{
608+
_bt_buildadd(index, state, bti2);
609+
if (should_free2)
610+
pfree((void *) bti2);
611+
bti2 = (BTItem) tuplesort_getindextuple(btspool2->sortstate, true, &should_free2);
612+
}
613+
}
614+
_bt_freeskey(indexScanKey);
615+
}
616+
else /* merge is unnecessary */
617+
{
618+
while (bti = (BTItem) tuplesort_getindextuple(btspool->sortstate, true, &should_free), bti != (BTItem) NULL)
619+
{
620+
/* When we see first tuple, create first index page */
621+
if (state == NULL)
622+
state = _bt_pagestate(index, BTP_LEAF, 0);
545623

546-
if (should_free)
547-
pfree((void *) bti);
624+
_bt_buildadd(index, state, bti);
625+
if (should_free)
626+
pfree((void *) bti);
627+
}
548628
}
549629

550630
/* Close down final pages, if we had any data at all */

src/include/access/nbtree.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: nbtree.h,v 1.40 2000/07/25 04:47:57 tgl Exp $
10+
* $Id: nbtree.h,v 1.41 2000/08/10 02:33:19 inoue Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -289,6 +289,6 @@ typedef struct BTSpool BTSpool; /* opaque type known only within nbtsort.c */
289289
extern BTSpool *_bt_spoolinit(Relation index, bool isunique);
290290
extern void _bt_spooldestroy(BTSpool *btspool);
291291
extern void _bt_spool(BTItem btitem, BTSpool *btspool);
292-
extern void _bt_leafbuild(BTSpool *btspool);
292+
extern void _bt_leafbuild(BTSpool *btspool, BTSpool *spool2);
293293

294294
#endif /* NBTREE_H */

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