From c82dedb7a8a953785f24a3b10de376760d60c24c Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Wed, 29 Aug 2012 09:14:08 +0300 Subject: [PATCH] Optimize SP-GiST insertions. This includes two micro-optimizations to the tight inner loop in descending the SP-GiST tree: 1. avoid an extra function call to index_getprocinfo when calling user-defined choose function, and 2. avoid a useless palloc+pfree when node labels are not used. --- src/backend/access/spgist/spgdoinsert.c | 10 ++++++-- src/backend/access/spgist/spgutils.c | 33 ++++++++++++++----------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/backend/access/spgist/spgdoinsert.c b/src/backend/access/spgist/spgdoinsert.c index b3f8f6a231..36d0570362 100644 --- a/src/backend/access/spgist/spgdoinsert.c +++ b/src/backend/access/spgist/spgdoinsert.c @@ -1861,6 +1861,14 @@ spgdoinsert(Relation index, SpGistState *state, int leafSize; SPPageDesc current, parent; + FmgrInfo *procinfo = NULL; + + /* + * Look up FmgrInfo of the user-defined choose function once, to save + * cycles in the loop below. + */ + if (!isnull) + procinfo = index_getprocinfo(index, 1, SPGIST_CHOOSE_PROC); /* * Since we don't use index_form_tuple in this AM, we have to make sure @@ -2007,7 +2015,6 @@ spgdoinsert(Relation index, SpGistState *state, SpGistInnerTuple innerTuple; spgChooseIn in; spgChooseOut out; - FmgrInfo *procinfo; /* * spgAddNode and spgSplitTuple cases will loop back to here to @@ -2035,7 +2042,6 @@ spgdoinsert(Relation index, SpGistState *state, if (!isnull) { /* use user-defined choose method */ - procinfo = index_getprocinfo(index, 1, SPGIST_CHOOSE_PROC); FunctionCall2Coll(procinfo, index->rd_indcollation[0], PointerGetDatum(&in), diff --git a/src/backend/access/spgist/spgutils.c b/src/backend/access/spgist/spgutils.c index 72aae02b45..675c80eb39 100644 --- a/src/backend/access/spgist/spgutils.c +++ b/src/backend/access/spgist/spgutils.c @@ -743,27 +743,32 @@ Datum * spgExtractNodeLabels(SpGistState *state, SpGistInnerTuple innerTuple) { Datum *nodeLabels; - int nullcount = 0; int i; SpGistNodeTuple node; - nodeLabels = (Datum *) palloc(sizeof(Datum) * innerTuple->nNodes); - SGITITERATE(innerTuple, i, node) - { - if (IndexTupleHasNulls(node)) - nullcount++; - else - nodeLabels[i] = SGNTDATUM(node, state); - } - if (nullcount == innerTuple->nNodes) + /* Either all the labels must be NULL, or none. */ + node = SGITNODEPTR(innerTuple); + if (IndexTupleHasNulls(node)) { + SGITITERATE(innerTuple, i, node) + { + if (!IndexTupleHasNulls(node)) + elog(ERROR, "some but not all node labels are null in SPGiST inner tuple"); + } /* They're all null, so just return NULL */ - pfree(nodeLabels); return NULL; } - if (nullcount != 0) - elog(ERROR, "some but not all node labels are null in SPGiST inner tuple"); - return nodeLabels; + else + { + nodeLabels = (Datum *) palloc(sizeof(Datum) * innerTuple->nNodes); + SGITITERATE(innerTuple, i, node) + { + if (IndexTupleHasNulls(node)) + elog(ERROR, "some but not all node labels are null in SPGiST inner tuple"); + nodeLabels[i] = SGNTDATUM(node, state); + } + return nodeLabels; + } } /*