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.
This commit is contained in:
Heikki Linnakangas 2012-08-29 09:14:08 +03:00
parent 9df55c8c3f
commit c82dedb7a8
2 changed files with 27 additions and 16 deletions

View File

@ -1861,6 +1861,14 @@ spgdoinsert(Relation index, SpGistState *state,
int leafSize; int leafSize;
SPPageDesc current, SPPageDesc current,
parent; 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 * 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; SpGistInnerTuple innerTuple;
spgChooseIn in; spgChooseIn in;
spgChooseOut out; spgChooseOut out;
FmgrInfo *procinfo;
/* /*
* spgAddNode and spgSplitTuple cases will loop back to here to * spgAddNode and spgSplitTuple cases will loop back to here to
@ -2035,7 +2042,6 @@ spgdoinsert(Relation index, SpGistState *state,
if (!isnull) if (!isnull)
{ {
/* use user-defined choose method */ /* use user-defined choose method */
procinfo = index_getprocinfo(index, 1, SPGIST_CHOOSE_PROC);
FunctionCall2Coll(procinfo, FunctionCall2Coll(procinfo,
index->rd_indcollation[0], index->rd_indcollation[0],
PointerGetDatum(&in), PointerGetDatum(&in),

View File

@ -743,27 +743,32 @@ Datum *
spgExtractNodeLabels(SpGistState *state, SpGistInnerTuple innerTuple) spgExtractNodeLabels(SpGistState *state, SpGistInnerTuple innerTuple)
{ {
Datum *nodeLabels; Datum *nodeLabels;
int nullcount = 0;
int i; int i;
SpGistNodeTuple node; SpGistNodeTuple node;
nodeLabels = (Datum *) palloc(sizeof(Datum) * innerTuple->nNodes); /* Either all the labels must be NULL, or none. */
SGITITERATE(innerTuple, i, node) node = SGITNODEPTR(innerTuple);
{ if (IndexTupleHasNulls(node))
if (IndexTupleHasNulls(node))
nullcount++;
else
nodeLabels[i] = SGNTDATUM(node, state);
}
if (nullcount == innerTuple->nNodes)
{ {
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 */ /* They're all null, so just return NULL */
pfree(nodeLabels);
return NULL; return NULL;
} }
if (nullcount != 0) else
elog(ERROR, "some but not all node labels are null in SPGiST inner tuple"); {
return nodeLabels; 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;
}
} }
/* /*