mirror of https://github.com/postgres/postgres
Add amgettreeheight index AM API routine
The only current implementation is for btree where it calls _bt_getrootheight(). Other index types can now also use this to pass information to their amcostestimate routine. Previously, btree was hardcoded and other index types could not hook into the optimizer at this point. Author: Mark Dilger <mark.dilger@enterprisedb.com> Discussion: https://www.postgresql.org/message-id/flat/E72EAA49-354D-4C2E-8EB9-255197F55330@enterprisedb.com
This commit is contained in:
parent
f5050f795a
commit
56fead44dc
|
@ -137,6 +137,7 @@ blhandler(PG_FUNCTION_ARGS)
|
|||
amroutine->amvacuumcleanup = blvacuumcleanup;
|
||||
amroutine->amcanreturn = NULL;
|
||||
amroutine->amcostestimate = blcostestimate;
|
||||
amroutine->amgettreeheight = NULL;
|
||||
amroutine->amoptions = bloptions;
|
||||
amroutine->amproperty = NULL;
|
||||
amroutine->ambuildphasename = NULL;
|
||||
|
|
|
@ -146,6 +146,7 @@ typedef struct IndexAmRoutine
|
|||
amvacuumcleanup_function amvacuumcleanup;
|
||||
amcanreturn_function amcanreturn; /* can be NULL */
|
||||
amcostestimate_function amcostestimate;
|
||||
amgettreeheight_function amgettreeheight; /* can be NULL */
|
||||
amoptions_function amoptions;
|
||||
amproperty_function amproperty; /* can be NULL */
|
||||
ambuildphasename_function ambuildphasename; /* can be NULL */
|
||||
|
@ -480,6 +481,21 @@ amcostestimate (PlannerInfo *root,
|
|||
|
||||
<para>
|
||||
<programlisting>
|
||||
int
|
||||
amgettreeheight (Relation rel);
|
||||
</programlisting>
|
||||
Compute the height of a tree-shaped index. This information is supplied to
|
||||
the <function>amcostestimate</function> function in
|
||||
<literal>path->indexinfo->tree_height</literal> and can be used to support
|
||||
the cost estimation. The result is not used anywhere else, so this
|
||||
function can actually be used to compute any kind of data (that fits into
|
||||
an integer) about the index that the cost estimation function might want to
|
||||
know. If the computation is expensive, it could be useful to cache the
|
||||
result as part of <literal>RelationData.rd_amcache</literal>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<programlisting>
|
||||
bytea *
|
||||
amoptions (ArrayType *reloptions,
|
||||
bool validate);
|
||||
|
|
|
@ -279,6 +279,7 @@ brinhandler(PG_FUNCTION_ARGS)
|
|||
amroutine->amvacuumcleanup = brinvacuumcleanup;
|
||||
amroutine->amcanreturn = NULL;
|
||||
amroutine->amcostestimate = brincostestimate;
|
||||
amroutine->amgettreeheight = NULL;
|
||||
amroutine->amoptions = brinoptions;
|
||||
amroutine->amproperty = NULL;
|
||||
amroutine->ambuildphasename = NULL;
|
||||
|
|
|
@ -69,6 +69,7 @@ ginhandler(PG_FUNCTION_ARGS)
|
|||
amroutine->amvacuumcleanup = ginvacuumcleanup;
|
||||
amroutine->amcanreturn = NULL;
|
||||
amroutine->amcostestimate = gincostestimate;
|
||||
amroutine->amgettreeheight = NULL;
|
||||
amroutine->amoptions = ginoptions;
|
||||
amroutine->amproperty = NULL;
|
||||
amroutine->ambuildphasename = NULL;
|
||||
|
|
|
@ -91,6 +91,7 @@ gisthandler(PG_FUNCTION_ARGS)
|
|||
amroutine->amvacuumcleanup = gistvacuumcleanup;
|
||||
amroutine->amcanreturn = gistcanreturn;
|
||||
amroutine->amcostestimate = gistcostestimate;
|
||||
amroutine->amgettreeheight = NULL;
|
||||
amroutine->amoptions = gistoptions;
|
||||
amroutine->amproperty = gistproperty;
|
||||
amroutine->ambuildphasename = NULL;
|
||||
|
|
|
@ -89,6 +89,7 @@ hashhandler(PG_FUNCTION_ARGS)
|
|||
amroutine->amvacuumcleanup = hashvacuumcleanup;
|
||||
amroutine->amcanreturn = NULL;
|
||||
amroutine->amcostestimate = hashcostestimate;
|
||||
amroutine->amgettreeheight = NULL;
|
||||
amroutine->amoptions = hashoptions;
|
||||
amroutine->amproperty = NULL;
|
||||
amroutine->ambuildphasename = NULL;
|
||||
|
|
|
@ -133,6 +133,7 @@ bthandler(PG_FUNCTION_ARGS)
|
|||
amroutine->amvacuumcleanup = btvacuumcleanup;
|
||||
amroutine->amcanreturn = btcanreturn;
|
||||
amroutine->amcostestimate = btcostestimate;
|
||||
amroutine->amgettreeheight = btgettreeheight;
|
||||
amroutine->amoptions = btoptions;
|
||||
amroutine->amproperty = btproperty;
|
||||
amroutine->ambuildphasename = btbuildphasename;
|
||||
|
@ -1445,3 +1446,12 @@ btcanreturn(Relation index, int attno)
|
|||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* btgettreeheight() -- Compute tree height for use by btcostestimate().
|
||||
*/
|
||||
int
|
||||
btgettreeheight(Relation rel)
|
||||
{
|
||||
return _bt_getrootheight(rel);
|
||||
}
|
||||
|
|
|
@ -76,6 +76,7 @@ spghandler(PG_FUNCTION_ARGS)
|
|||
amroutine->amvacuumcleanup = spgvacuumcleanup;
|
||||
amroutine->amcanreturn = spgcanreturn;
|
||||
amroutine->amcostestimate = spgcostestimate;
|
||||
amroutine->amgettreeheight = NULL;
|
||||
amroutine->amoptions = spgoptions;
|
||||
amroutine->amproperty = spgproperty;
|
||||
amroutine->ambuildphasename = NULL;
|
||||
|
|
|
@ -241,7 +241,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
|
|||
Oid indexoid = lfirst_oid(l);
|
||||
Relation indexRelation;
|
||||
Form_pg_index index;
|
||||
IndexAmRoutine *amroutine;
|
||||
IndexAmRoutine *amroutine = NULL;
|
||||
IndexOptInfo *info;
|
||||
int ncolumns,
|
||||
nkeycolumns;
|
||||
|
@ -485,13 +485,12 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
|
|||
info->tuples = rel->tuples;
|
||||
}
|
||||
|
||||
if (info->relam == BTREE_AM_OID)
|
||||
{
|
||||
/*
|
||||
* For btrees, get tree height while we have the index
|
||||
* open
|
||||
* Get tree height while we have the index open
|
||||
*/
|
||||
info->tree_height = _bt_getrootheight(indexRelation);
|
||||
if (amroutine->amgettreeheight)
|
||||
{
|
||||
info->tree_height = amroutine->amgettreeheight(indexRelation);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -140,6 +140,13 @@ typedef void (*amcostestimate_function) (struct PlannerInfo *root,
|
|||
double *indexCorrelation,
|
||||
double *indexPages);
|
||||
|
||||
/* estimate height of a tree-structured index
|
||||
*
|
||||
* XXX This just computes a value that is later used by amcostestimate. This
|
||||
* API could be expanded to support passing more values if the need arises.
|
||||
*/
|
||||
typedef int (*amgettreeheight_function) (Relation rel);
|
||||
|
||||
/* parse index reloptions */
|
||||
typedef bytea *(*amoptions_function) (Datum reloptions,
|
||||
bool validate);
|
||||
|
@ -272,6 +279,7 @@ typedef struct IndexAmRoutine
|
|||
amvacuumcleanup_function amvacuumcleanup;
|
||||
amcanreturn_function amcanreturn; /* can be NULL */
|
||||
amcostestimate_function amcostestimate;
|
||||
amgettreeheight_function amgettreeheight; /* can be NULL */
|
||||
amoptions_function amoptions;
|
||||
amproperty_function amproperty; /* can be NULL */
|
||||
ambuildphasename_function ambuildphasename; /* can be NULL */
|
||||
|
|
|
@ -1186,6 +1186,7 @@ extern IndexBulkDeleteResult *btbulkdelete(IndexVacuumInfo *info,
|
|||
extern IndexBulkDeleteResult *btvacuumcleanup(IndexVacuumInfo *info,
|
||||
IndexBulkDeleteResult *stats);
|
||||
extern bool btcanreturn(Relation index, int attno);
|
||||
extern int btgettreeheight(Relation rel);
|
||||
|
||||
/*
|
||||
* prototypes for internal functions in nbtree.c
|
||||
|
|
|
@ -308,6 +308,7 @@ dihandler(PG_FUNCTION_ARGS)
|
|||
amroutine->amvacuumcleanup = divacuumcleanup;
|
||||
amroutine->amcanreturn = NULL;
|
||||
amroutine->amcostestimate = dicostestimate;
|
||||
amroutine->amgettreeheight = NULL;
|
||||
amroutine->amoptions = dioptions;
|
||||
amroutine->amproperty = NULL;
|
||||
amroutine->ambuildphasename = NULL;
|
||||
|
|
Loading…
Reference in New Issue