diff options
| author | Robert Haas | 2014-07-01 14:34:42 +0000 |
|---|---|---|
| committer | Robert Haas | 2014-07-01 14:34:42 +0000 |
| commit | 9f03ca915196dfc871804a1f8aad26207f601fd6 (patch) | |
| tree | 15b68e977122a04e46917f085b7d70cedf1d3d73 /src/backend | |
| parent | 03a25cec8de3737924c9dd33bb868d4bc7a33ad5 (diff) | |
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.
Diffstat (limited to 'src/backend')
| -rw-r--r-- | src/backend/access/common/indextuple.c | 3 | ||||
| -rw-r--r-- | src/backend/access/hash/hash.c | 32 | ||||
| -rw-r--r-- | src/backend/access/hash/hashsort.c | 5 | ||||
| -rw-r--r-- | src/backend/access/nbtree/nbtree.c | 11 | ||||
| -rw-r--r-- | src/backend/access/nbtree/nbtsort.c | 5 | ||||
| -rw-r--r-- | src/backend/utils/sort/tuplesort.c | 23 |
6 files changed, 37 insertions, 42 deletions
diff --git a/src/backend/access/common/indextuple.c b/src/backend/access/common/indextuple.c index 5fd400990b7..8d9a8930389 100644 --- a/src/backend/access/common/indextuple.c +++ b/src/backend/access/common/indextuple.c @@ -28,6 +28,9 @@ /* ---------------- * index_form_tuple + * + * This shouldn't leak any memory; otherwise, callers such as + * tuplesort_putindextuplevalues() will be very unhappy. * ---------------- */ IndexTuple diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c index 7abb7a47fc2..925a58f4f64 100644 --- a/src/backend/access/hash/hash.c +++ b/src/backend/access/hash/hash.c @@ -142,26 +142,23 @@ hashbuildCallback(Relation index, HashBuildState *buildstate = (HashBuildState *) state; IndexTuple itup; - /* form an index tuple and point it at the heap tuple */ - itup = _hash_form_tuple(index, values, isnull); - itup->t_tid = htup->t_self; - /* Hash indexes don't index nulls, see notes in hashinsert */ - if (IndexTupleHasNulls(itup)) - { - pfree(itup); + if (isnull[0]) return; - } /* Either spool the tuple for sorting, or just put it into the index */ if (buildstate->spool) - _h_spool(itup, buildstate->spool); + _h_spool(buildstate->spool, &htup->t_self, values, isnull); else + { + /* form an index tuple and point it at the heap tuple */ + itup = _hash_form_tuple(index, values, isnull); + itup->t_tid = htup->t_self; _hash_doinsert(index, itup); + pfree(itup); + } buildstate->indtuples += 1; - - pfree(itup); } /* @@ -184,10 +181,6 @@ hashinsert(PG_FUNCTION_ARGS) #endif IndexTuple itup; - /* generate an index tuple */ - itup = _hash_form_tuple(rel, values, isnull); - itup->t_tid = *ht_ctid; - /* * If the single index key is null, we don't insert it into the index. * Hash tables support scans on '='. Relational algebra says that A = B @@ -197,11 +190,12 @@ hashinsert(PG_FUNCTION_ARGS) * NOTNULL scans, but that's an artifact of the strategy map architecture * chosen in 1986, not of the way nulls are handled here. */ - if (IndexTupleHasNulls(itup)) - { - pfree(itup); + if (isnull[0]) PG_RETURN_BOOL(false); - } + + /* generate an index tuple */ + itup = _hash_form_tuple(rel, values, isnull); + itup->t_tid = *ht_ctid; _hash_doinsert(rel, itup); diff --git a/src/backend/access/hash/hashsort.c b/src/backend/access/hash/hashsort.c index c0d6fec2567..faf4fc24e69 100644 --- a/src/backend/access/hash/hashsort.c +++ b/src/backend/access/hash/hashsort.c @@ -90,9 +90,10 @@ _h_spooldestroy(HSpool *hspool) * spool an index entry into the sort file. */ void -_h_spool(IndexTuple itup, HSpool *hspool) +_h_spool(HSpool *hspool, ItemPointer self, Datum *values, bool *isnull) { - tuplesort_putindextuple(hspool->sortstate, itup); + tuplesort_putindextuplevalues(hspool->sortstate, hspool->index, + self, values, isnull); } /* diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index 36dc6c278ea..89a98270798 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -171,28 +171,21 @@ btbuildCallback(Relation index, void *state) { BTBuildState *buildstate = (BTBuildState *) state; - IndexTuple itup; - - /* form an index tuple and point it at the heap tuple */ - itup = index_form_tuple(RelationGetDescr(index), values, isnull); - itup->t_tid = htup->t_self; /* * insert the index tuple into the appropriate spool file for subsequent * processing */ if (tupleIsAlive || buildstate->spool2 == NULL) - _bt_spool(itup, buildstate->spool); + _bt_spool(buildstate->spool, &htup->t_self, values, isnull); else { /* dead tuples are put into spool2 */ buildstate->haveDead = true; - _bt_spool(itup, buildstate->spool2); + _bt_spool(buildstate->spool2, &htup->t_self, values, isnull); } buildstate->indtuples += 1; - - pfree(itup); } /* diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c index 1281a120c56..048b2151186 100644 --- a/src/backend/access/nbtree/nbtsort.c +++ b/src/backend/access/nbtree/nbtsort.c @@ -185,9 +185,10 @@ _bt_spooldestroy(BTSpool *btspool) * spool an index entry into the sort file. */ void -_bt_spool(IndexTuple itup, BTSpool *btspool) +_bt_spool(BTSpool *btspool, ItemPointer self, Datum *values, bool *isnull) { - tuplesort_putindextuple(btspool->sortstate, itup); + tuplesort_putindextuplevalues(btspool->sortstate, btspool->index, + self, values, isnull); } /* diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c index aa0f6d8e047..426a64af867 100644 --- a/src/backend/utils/sort/tuplesort.c +++ b/src/backend/utils/sort/tuplesort.c @@ -1134,22 +1134,25 @@ tuplesort_putheaptuple(Tuplesortstate *state, HeapTuple tup) } /* - * Accept one index tuple while collecting input data for sort. - * - * Note that the input tuple is always copied; the caller need not save it. + * Collect one index tuple while collecting input data for sort, building + * it from caller-supplied values. */ void -tuplesort_putindextuple(Tuplesortstate *state, IndexTuple tuple) +tuplesort_putindextuplevalues(Tuplesortstate *state, Relation rel, + ItemPointer self, Datum *values, + bool *isnull) { MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext); SortTuple stup; - /* - * Copy the given tuple into memory we control, and decrease availMem. - * Then call the common code. - */ - COPYTUP(state, &stup, (void *) tuple); - + stup.tuple = index_form_tuple(RelationGetDescr(rel), values, isnull); + ((IndexTuple) stup.tuple)->t_tid = *self; + USEMEM(state, GetMemoryChunkSpace(stup.tuple)); + /* set up first-column key value */ + stup.datum1 = index_getattr((IndexTuple) stup.tuple, + 1, + RelationGetDescr(state->indexRel), + &stup.isnull1); puttuple_common(state, &stup); MemoryContextSwitchTo(oldcontext); |
