mirror of
https://github.com/postgres/postgres.git
synced 2025-04-22 23:02:54 +03:00
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:
parent
9df55c8c3f
commit
c82dedb7a8
@ -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),
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user