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

Commit 9f03ca9

Browse files
committed
Avoid copying index tuples when building an index.
The previous code, perhaps out of concern for avoid memory leaks, formed the tuple in one memory context and then copied it to another memory context. However, this doesn't appear to be necessary, since index_form_tuple and the functions it calls take precautions against leaking memory. In my testing, building the tuple directly inside the sort context shaves several percent off the index build time. Rearrange things so we do that. Patch by me. Review by Amit Kapila, Tom Lane, Andres Freund.
1 parent 03a25ce commit 9f03ca9

File tree

9 files changed

+44
-45
lines changed

9 files changed

+44
-45
lines changed

src/backend/access/common/indextuple.c

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828

2929
/* ----------------
3030
* index_form_tuple
31+
*
32+
* This shouldn't leak any memory; otherwise, callers such as
33+
* tuplesort_putindextuplevalues() will be very unhappy.
3134
* ----------------
3235
*/
3336
IndexTuple

src/backend/access/hash/hash.c

+13-19
Original file line numberDiff line numberDiff line change
@@ -142,26 +142,23 @@ hashbuildCallback(Relation index,
142142
HashBuildState *buildstate = (HashBuildState *) state;
143143
IndexTuple itup;
144144

145-
/* form an index tuple and point it at the heap tuple */
146-
itup = _hash_form_tuple(index, values, isnull);
147-
itup->t_tid = htup->t_self;
148-
149145
/* Hash indexes don't index nulls, see notes in hashinsert */
150-
if (IndexTupleHasNulls(itup))
151-
{
152-
pfree(itup);
146+
if (isnull[0])
153147
return;
154-
}
155148

156149
/* Either spool the tuple for sorting, or just put it into the index */
157150
if (buildstate->spool)
158-
_h_spool(itup, buildstate->spool);
151+
_h_spool(buildstate->spool, &htup->t_self, values, isnull);
159152
else
153+
{
154+
/* form an index tuple and point it at the heap tuple */
155+
itup = _hash_form_tuple(index, values, isnull);
156+
itup->t_tid = htup->t_self;
160157
_hash_doinsert(index, itup);
158+
pfree(itup);
159+
}
161160

162161
buildstate->indtuples += 1;
163-
164-
pfree(itup);
165162
}
166163

167164
/*
@@ -184,10 +181,6 @@ hashinsert(PG_FUNCTION_ARGS)
184181
#endif
185182
IndexTuple itup;
186183

187-
/* generate an index tuple */
188-
itup = _hash_form_tuple(rel, values, isnull);
189-
itup->t_tid = *ht_ctid;
190-
191184
/*
192185
* If the single index key is null, we don't insert it into the index.
193186
* Hash tables support scans on '='. Relational algebra says that A = B
@@ -197,11 +190,12 @@ hashinsert(PG_FUNCTION_ARGS)
197190
* NOTNULL scans, but that's an artifact of the strategy map architecture
198191
* chosen in 1986, not of the way nulls are handled here.
199192
*/
200-
if (IndexTupleHasNulls(itup))
201-
{
202-
pfree(itup);
193+
if (isnull[0])
203194
PG_RETURN_BOOL(false);
204-
}
195+
196+
/* generate an index tuple */
197+
itup = _hash_form_tuple(rel, values, isnull);
198+
itup->t_tid = *ht_ctid;
205199

206200
_hash_doinsert(rel, itup);
207201

src/backend/access/hash/hashsort.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,10 @@ _h_spooldestroy(HSpool *hspool)
9090
* spool an index entry into the sort file.
9191
*/
9292
void
93-
_h_spool(IndexTuple itup, HSpool *hspool)
93+
_h_spool(HSpool *hspool, ItemPointer self, Datum *values, bool *isnull)
9494
{
95-
tuplesort_putindextuple(hspool->sortstate, itup);
95+
tuplesort_putindextuplevalues(hspool->sortstate, hspool->index,
96+
self, values, isnull);
9697
}
9798

9899
/*

src/backend/access/nbtree/nbtree.c

+2-9
Original file line numberDiff line numberDiff line change
@@ -171,28 +171,21 @@ btbuildCallback(Relation index,
171171
void *state)
172172
{
173173
BTBuildState *buildstate = (BTBuildState *) state;
174-
IndexTuple itup;
175-
176-
/* form an index tuple and point it at the heap tuple */
177-
itup = index_form_tuple(RelationGetDescr(index), values, isnull);
178-
itup->t_tid = htup->t_self;
179174

180175
/*
181176
* insert the index tuple into the appropriate spool file for subsequent
182177
* processing
183178
*/
184179
if (tupleIsAlive || buildstate->spool2 == NULL)
185-
_bt_spool(itup, buildstate->spool);
180+
_bt_spool(buildstate->spool, &htup->t_self, values, isnull);
186181
else
187182
{
188183
/* dead tuples are put into spool2 */
189184
buildstate->haveDead = true;
190-
_bt_spool(itup, buildstate->spool2);
185+
_bt_spool(buildstate->spool2, &htup->t_self, values, isnull);
191186
}
192187

193188
buildstate->indtuples += 1;
194-
195-
pfree(itup);
196189
}
197190

198191
/*

src/backend/access/nbtree/nbtsort.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,10 @@ _bt_spooldestroy(BTSpool *btspool)
185185
* spool an index entry into the sort file.
186186
*/
187187
void
188-
_bt_spool(IndexTuple itup, BTSpool *btspool)
188+
_bt_spool(BTSpool *btspool, ItemPointer self, Datum *values, bool *isnull)
189189
{
190-
tuplesort_putindextuple(btspool->sortstate, itup);
190+
tuplesort_putindextuplevalues(btspool->sortstate, btspool->index,
191+
self, values, isnull);
191192
}
192193

193194
/*

src/backend/utils/sort/tuplesort.c

+13-10
Original file line numberDiff line numberDiff line change
@@ -1134,22 +1134,25 @@ tuplesort_putheaptuple(Tuplesortstate *state, HeapTuple tup)
11341134
}
11351135

11361136
/*
1137-
* Accept one index tuple while collecting input data for sort.
1138-
*
1139-
* Note that the input tuple is always copied; the caller need not save it.
1137+
* Collect one index tuple while collecting input data for sort, building
1138+
* it from caller-supplied values.
11401139
*/
11411140
void
1142-
tuplesort_putindextuple(Tuplesortstate *state, IndexTuple tuple)
1141+
tuplesort_putindextuplevalues(Tuplesortstate *state, Relation rel,
1142+
ItemPointer self, Datum *values,
1143+
bool *isnull)
11431144
{
11441145
MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
11451146
SortTuple stup;
11461147

1147-
/*
1148-
* Copy the given tuple into memory we control, and decrease availMem.
1149-
* Then call the common code.
1150-
*/
1151-
COPYTUP(state, &stup, (void *) tuple);
1152-
1148+
stup.tuple = index_form_tuple(RelationGetDescr(rel), values, isnull);
1149+
((IndexTuple) stup.tuple)->t_tid = *self;
1150+
USEMEM(state, GetMemoryChunkSpace(stup.tuple));
1151+
/* set up first-column key value */
1152+
stup.datum1 = index_getattr((IndexTuple) stup.tuple,
1153+
1,
1154+
RelationGetDescr(state->indexRel),
1155+
&stup.isnull1);
11531156
puttuple_common(state, &stup);
11541157

11551158
MemoryContextSwitchTo(oldcontext);

src/include/access/hash.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,8 @@ typedef struct HSpool HSpool; /* opaque struct in hashsort.c */
336336

337337
extern HSpool *_h_spoolinit(Relation heap, Relation index, uint32 num_buckets);
338338
extern void _h_spooldestroy(HSpool *hspool);
339-
extern void _h_spool(IndexTuple itup, HSpool *hspool);
339+
extern void _h_spool(HSpool *hspool, ItemPointer self,
340+
Datum *values, bool *isnull);
340341
extern void _h_indexbuild(HSpool *hspool);
341342

342343
/* hashutil.c */

src/include/access/nbtree.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,8 @@ typedef struct BTSpool BTSpool; /* opaque type known only within nbtsort.c */
717717
extern BTSpool *_bt_spoolinit(Relation heap, Relation index,
718718
bool isunique, bool isdead);
719719
extern void _bt_spooldestroy(BTSpool *btspool);
720-
extern void _bt_spool(IndexTuple itup, BTSpool *btspool);
720+
extern void _bt_spool(BTSpool *btspool, ItemPointer self,
721+
Datum *values, bool *isnull);
721722
extern void _bt_leafbuild(BTSpool *btspool, BTSpool *spool2);
722723

723724
/*

src/include/utils/tuplesort.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,9 @@ extern void tuplesort_set_bound(Tuplesortstate *state, int64 bound);
8484
extern void tuplesort_puttupleslot(Tuplesortstate *state,
8585
TupleTableSlot *slot);
8686
extern void tuplesort_putheaptuple(Tuplesortstate *state, HeapTuple tup);
87-
extern void tuplesort_putindextuple(Tuplesortstate *state, IndexTuple tuple);
87+
extern void tuplesort_putindextuplevalues(Tuplesortstate *state,
88+
Relation rel, ItemPointer self,
89+
Datum *values, bool *isnull);
8890
extern void tuplesort_putdatum(Tuplesortstate *state, Datum val,
8991
bool isNull);
9092

0 commit comments

Comments
 (0)