diff options
Diffstat (limited to 'src/backend/optimizer/util')
-rw-r--r-- | src/backend/optimizer/util/pathnode.c | 123 | ||||
-rw-r--r-- | src/backend/optimizer/util/plancat.c | 475 | ||||
-rw-r--r-- | src/backend/optimizer/util/relnode.c | 16 |
3 files changed, 235 insertions, 379 deletions
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index 0f9bf1b8bbb..a2551391e00 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.55 1999/11/23 20:07:00 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.56 2000/01/09 00:26:37 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -15,8 +15,6 @@ #include "postgres.h" - - #include "optimizer/cost.h" #include "optimizer/pathnode.h" #include "optimizer/paths.h" @@ -37,10 +35,7 @@ bool path_is_cheaper(Path *path1, Path *path2) { - Cost cost1 = path1->path_cost; - Cost cost2 = path2->path_cost; - - return (bool) (cost1 < cost2); + return (bool) (path1->path_cost < path2->path_cost); } /* @@ -60,8 +55,8 @@ set_cheapest(RelOptInfo *parent_rel, List *pathlist) List *p; Path *cheapest_so_far; - Assert(pathlist != NIL); Assert(IsA(parent_rel, RelOptInfo)); + Assert(pathlist != NIL); cheapest_so_far = (Path *) lfirst(pathlist); @@ -192,18 +187,11 @@ Path * create_seqscan_path(RelOptInfo *rel) { Path *pathnode = makeNode(Path); - int relid = 0; pathnode->pathtype = T_SeqScan; pathnode->parent = rel; - pathnode->path_cost = 0.0; pathnode->pathkeys = NIL; /* seqscan has unordered result */ - - if (rel->relids != NIL) /* can this happen? */ - relid = lfirsti(rel->relids); - - pathnode->path_cost = cost_seqscan(relid, - rel->pages, rel->tuples); + pathnode->path_cost = cost_seqscan(rel); return pathnode; } @@ -222,7 +210,7 @@ create_seqscan_path(RelOptInfo *rel) IndexPath * create_index_path(Query *root, RelOptInfo *rel, - RelOptInfo *index, + IndexOptInfo *index, List *restriction_clauses) { IndexPath *pathnode = makeNode(IndexPath); @@ -239,8 +227,7 @@ create_index_path(Query *root, * conditions. If we do have restriction conditions to use, they * will get inserted below. */ - Assert(length(index->relids) == 1); - pathnode->indexid = index->relids; + pathnode->indexid = lconsi(index->indexoid, NIL); pathnode->indexqual = lcons(NIL, NIL); pathnode->joinrelids = NIL; /* no join clauses here */ @@ -250,13 +237,9 @@ create_index_path(Query *root, * We have no restriction clauses, so compute scan cost using * selectivity of 1.0. */ - pathnode->path.path_cost = cost_index(lfirsti(index->relids), + pathnode->path.path_cost = cost_index(rel, index, index->pages, - 1.0, - rel->pages, - rel->tuples, - index->pages, - index->tuples, + (Selectivity) 1.0, false); } else @@ -266,9 +249,8 @@ create_index_path(Query *root, * restriction clause(s). Also, place indexqual in path node. */ List *indexquals; - float npages; - float selec; - Cost clausesel; + long npages; + Selectivity selec; indexquals = get_actual_clauses(restriction_clauses); /* expand special operators to indexquals the executor can handle */ @@ -280,39 +262,15 @@ create_index_path(Query *root, lfirst(pathnode->indexqual) = indexquals; index_selectivity(root, - lfirsti(rel->relids), - lfirsti(index->relids), + rel, + index, indexquals, &npages, &selec); - pathnode->path.path_cost = cost_index(lfirsti(index->relids), - (int) npages, - selec, - rel->pages, - rel->tuples, - index->pages, - index->tuples, + pathnode->path.path_cost = cost_index(rel, index, + npages, selec, false); - - /* - * Set selectivities of clauses used with index to the selectivity - * of this index, subdividing the selectivity equally over each of - * the clauses. To the extent that index_selectivity() can make a - * better estimate of the joint selectivity of these clauses than - * the product of individual estimates from compute_clause_selec() - * would be, this should give us a more accurate estimate of the - * total selectivity of all the clauses. - * - * XXX If there is more than one useful index for this rel, and the - * indexes can be used with different but overlapping groups of - * restriction clauses, we may end up with too optimistic an estimate, - * since set_clause_selectivities() will save the minimum of the - * per-clause selectivity estimated with each index. But that should - * be fairly unlikely for typical index usage. - */ - clausesel = pow(selec, 1.0 / (double) length(restriction_clauses)); - set_clause_selectivities(restriction_clauses, clausesel); } return pathnode; @@ -331,14 +289,12 @@ create_tidscan_path(RelOptInfo *rel, List *tideval) pathnode->path.pathtype = T_TidScan; pathnode->path.parent = rel; - pathnode->path.path_cost = 0.0; pathnode->path.pathkeys = NIL; - - pathnode->path.path_cost = cost_tidscan(tideval); + pathnode->path.path_cost = cost_tidscan(rel, tideval); /* divide selectivity for each clause to get an equal selectivity * as IndexScan does OK ? */ - pathnode->tideval = copyObject(tideval); + pathnode->tideval = copyObject(tideval); /* is copy really necessary? */ pathnode->unjoined_relids = NIL; return pathnode; @@ -350,7 +306,6 @@ create_tidscan_path(RelOptInfo *rel, List *tideval) * relations. * * 'joinrel' is the join relation. - * 'outer_rel' is the outer join relation * 'outer_path' is the outer path * 'inner_path' is the inner path * 'pathkeys' are the path keys of the new join path @@ -360,7 +315,6 @@ create_tidscan_path(RelOptInfo *rel, List *tideval) */ NestPath * create_nestloop_path(RelOptInfo *joinrel, - RelOptInfo *outer_rel, Path *outer_path, Path *inner_path, List *pathkeys) @@ -371,15 +325,10 @@ create_nestloop_path(RelOptInfo *joinrel, pathnode->path.parent = joinrel; pathnode->outerjoinpath = outer_path; pathnode->innerjoinpath = inner_path; - pathnode->pathinfo = joinrel->restrictinfo; pathnode->path.pathkeys = pathkeys; - pathnode->path.path_cost = cost_nestloop(outer_path->path_cost, - inner_path->path_cost, - outer_rel->size, - inner_path->parent->size, - page_size(outer_rel->size, - outer_rel->width), + pathnode->path.path_cost = cost_nestloop(outer_path, + inner_path, IsA(inner_path, IndexPath)); return pathnode; @@ -391,10 +340,6 @@ create_nestloop_path(RelOptInfo *joinrel, * two relations * * 'joinrel' is the join relation - * 'outersize' is the number of tuples in the outer relation - * 'innersize' is the number of tuples in the inner relation - * 'outerwidth' is the number of bytes per tuple in the outer relation - * 'innerwidth' is the number of bytes per tuple in the inner relation * 'outer_path' is the outer path * 'inner_path' is the inner path * 'pathkeys' are the path keys of the new join path @@ -405,10 +350,6 @@ create_nestloop_path(RelOptInfo *joinrel, */ MergePath * create_mergejoin_path(RelOptInfo *joinrel, - int outersize, - int innersize, - int outerwidth, - int innerwidth, Path *outer_path, Path *inner_path, List *pathkeys, @@ -433,19 +374,14 @@ create_mergejoin_path(RelOptInfo *joinrel, pathnode->jpath.path.parent = joinrel; pathnode->jpath.outerjoinpath = outer_path; pathnode->jpath.innerjoinpath = inner_path; - pathnode->jpath.pathinfo = joinrel->restrictinfo; pathnode->jpath.path.pathkeys = pathkeys; pathnode->path_mergeclauses = mergeclauses; pathnode->outersortkeys = outersortkeys; pathnode->innersortkeys = innersortkeys; - pathnode->jpath.path.path_cost = cost_mergejoin(outer_path->path_cost, - inner_path->path_cost, + pathnode->jpath.path.path_cost = cost_mergejoin(outer_path, + inner_path, outersortkeys, - innersortkeys, - outersize, - innersize, - outerwidth, - innerwidth); + innersortkeys); return pathnode; } @@ -455,10 +391,6 @@ create_mergejoin_path(RelOptInfo *joinrel, * Creates a pathnode corresponding to a hash join between two relations. * * 'joinrel' is the join relation - * 'outersize' is the number of tuples in the outer relation - * 'innersize' is the number of tuples in the inner relation - * 'outerwidth' is the number of bytes per tuple in the outer relation - * 'innerwidth' is the number of bytes per tuple in the inner relation * 'outer_path' is the cheapest outer path * 'inner_path' is the cheapest inner path * 'hashclauses' is a list of the hash join clause (always a 1-element list) @@ -467,14 +399,10 @@ create_mergejoin_path(RelOptInfo *joinrel, */ HashPath * create_hashjoin_path(RelOptInfo *joinrel, - int outersize, - int innersize, - int outerwidth, - int innerwidth, Path *outer_path, Path *inner_path, List *hashclauses, - Cost innerdisbursion) + Selectivity innerdisbursion) { HashPath *pathnode = makeNode(HashPath); @@ -482,14 +410,11 @@ create_hashjoin_path(RelOptInfo *joinrel, pathnode->jpath.path.parent = joinrel; pathnode->jpath.outerjoinpath = outer_path; pathnode->jpath.innerjoinpath = inner_path; - pathnode->jpath.pathinfo = joinrel->restrictinfo; /* A hashjoin never has pathkeys, since its ordering is unpredictable */ pathnode->jpath.path.pathkeys = NIL; pathnode->path_hashclauses = hashclauses; - pathnode->jpath.path.path_cost = cost_hashjoin(outer_path->path_cost, - inner_path->path_cost, - outersize, innersize, - outerwidth, innerwidth, + pathnode->jpath.path.path_cost = cost_hashjoin(outer_path, + inner_path, innerdisbursion); return pathnode; diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 03d29be4dcf..ef0dbfbda99 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -8,14 +8,15 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.40 1999/11/22 17:56:17 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.41 2000/01/09 00:26:40 tgl Exp $ * *------------------------------------------------------------------------- */ -#include <math.h> #include "postgres.h" +#include <math.h> + #include "access/genam.h" #include "access/heapam.h" #include "catalog/catname.h" @@ -23,20 +24,12 @@ #include "catalog/pg_inherits.h" #include "optimizer/clauses.h" #include "optimizer/internal.h" +#include "optimizer/paths.h" #include "optimizer/plancat.h" #include "parser/parsetree.h" #include "utils/syscache.h" -static void IndexSelectivity(Oid indexrelid, Oid baserelid, int nIndexKeys, - Oid *operatorObjectIds, - AttrNumber *varAttributeNumbers, - Datum *constValues, - int *constFlags, - float *idxPages, - float *idxSelec); - - /* * relation_info - * Retrieves catalog information for a given relation. @@ -47,39 +40,33 @@ static void IndexSelectivity(Oid indexrelid, Oid baserelid, int nIndexKeys, */ void relation_info(Query *root, Index relid, - bool *hasindex, int *pages, int *tuples) + bool *hasindex, long *pages, double *tuples) { + Oid relationObjectId = getrelid(relid, root->rtable); HeapTuple relationTuple; Form_pg_class relation; - Oid relationObjectId; - relationObjectId = getrelid(relid, root->rtable); relationTuple = SearchSysCacheTuple(RELOID, ObjectIdGetDatum(relationObjectId), 0, 0, 0); - if (HeapTupleIsValid(relationTuple)) - { - relation = (Form_pg_class) GETSTRUCT(relationTuple); - - *hasindex = (relation->relhasindex) ? true : false; - *pages = relation->relpages; - *tuples = relation->reltuples; - } - else - { + if (!HeapTupleIsValid(relationTuple)) elog(ERROR, "relation_info: Relation %u not found", relationObjectId); - } + relation = (Form_pg_class) GETSTRUCT(relationTuple); + + *hasindex = (relation->relhasindex) ? true : false; + *pages = relation->relpages; + *tuples = relation->reltuples; } /* * find_secondary_indexes - * Creates a list of RelOptInfo nodes containing information for each + * Creates a list of IndexOptInfo nodes containing information for each * secondary index defined on the given relation. * * 'relid' is the RT index of the relation for which indices are being located * - * Returns a list of new index RelOptInfo nodes. + * Returns a list of new IndexOptInfo nodes. */ List * find_secondary_indexes(Query *root, Index relid) @@ -105,7 +92,7 @@ find_secondary_indexes(Query *root, Index relid) while (HeapTupleIsValid(indexTuple = heap_getnext(scan, 0))) { Form_pg_index index = (Form_pg_index) GETSTRUCT(indexTuple); - RelOptInfo *info = makeNode(RelOptInfo); + IndexOptInfo *info = makeNode(IndexOptInfo); int i; Relation indexRelation; uint16 amstrategy; @@ -120,7 +107,7 @@ find_secondary_indexes(Query *root, Index relid) info->ordering = (Oid *) palloc(sizeof(Oid) * (INDEX_MAX_KEYS+1)); /* Extract info from the pg_index tuple */ - info->relids = lconsi(index->indexrelid, NIL); + info->indexoid = index->indexrelid; info->indproc = index->indproc; /* functional index ?? */ if (VARSIZE(&index->indpred) != 0) /* partial index ?? */ { @@ -172,17 +159,6 @@ find_secondary_indexes(Query *root, Index relid) info->ordering[i] = ((Form_pg_amop) GETSTRUCT(amopTuple))->amopopr; } - info->indexed = false; /* not indexed itself */ - info->size = 0; - info->width = 0; - info->targetlist = NIL; - info->pathlist = NIL; - info->cheapestpath = NULL; - info->pruneable = true; - info->restrictinfo = NIL; - info->joininfo = NIL; - info->innerjoin = NIL; - indexes = lcons(info, indexes); } @@ -200,77 +176,211 @@ find_secondary_indexes(Query *root, Index relid) * but here we consider the cost of just one pass. * * 'root' is the query root - * 'relid' is the RT index of the relation being scanned - * 'indexid' is the OID of the index to be used + * 'rel' is the relation being scanned + * 'index' is the index to be used * 'indexquals' is the list of qual condition exprs (implicit AND semantics) * '*idxPages' receives an estimate of the number of index pages touched - * '*idxSelec' receives an estimate of selectivity of the scan + * '*idxSelec' receives an estimate of selectivity of the scan, ie fraction + * of the relation's tuples that will be retrieved */ void index_selectivity(Query *root, - int relid, - Oid indexid, + RelOptInfo *rel, + IndexOptInfo *index, List *indexquals, - float *idxPages, - float *idxSelec) + long *idxPages, + Selectivity *idxSelec) { - int nclauses = length(indexquals); - Oid *opno_array; - AttrNumber *attno_array; - Datum *value_array; - int *flag_array; + int relid; + Oid baserelid, + indexrelid; + HeapTuple indRel, + indexTuple; + Form_pg_class indexrelation; + Oid relam; + Form_pg_index pgindex; + int nIndexKeys; + float64data npages, + select, + fattr_select; + bool nphack = false; List *q; - int i; - if (nclauses <= 0) - { - *idxPages = 0.0; - *idxSelec = 1.0; - return; - } - opno_array = (Oid *) palloc(nclauses * sizeof(Oid)); - attno_array = (AttrNumber *) palloc(nclauses * sizeof(AttrNumber)); - value_array = (Datum *) palloc(nclauses * sizeof(Datum)); - flag_array = (int *) palloc(nclauses * sizeof(int)); + Assert(length(rel->relids) == 1); /* must be a base rel */ + relid = lfirsti(rel->relids); + + baserelid = getrelid(relid, root->rtable); + indexrelid = index->indexoid; + + indRel = SearchSysCacheTuple(RELOID, + ObjectIdGetDatum(indexrelid), + 0, 0, 0); + if (!HeapTupleIsValid(indRel)) + elog(ERROR, "index_selectivity: index %u not found in pg_class", + indexrelid); + indexrelation = (Form_pg_class) GETSTRUCT(indRel); + relam = indexrelation->relam; + + indexTuple = SearchSysCacheTuple(INDEXRELID, + ObjectIdGetDatum(indexrelid), + 0, 0, 0); + if (!HeapTupleIsValid(indexTuple)) + elog(ERROR, "index_selectivity: index %u not found in pg_index", + indexrelid); + pgindex = (Form_pg_index) GETSTRUCT(indexTuple); + + nIndexKeys = 1; + while (pgindex->indclass[nIndexKeys] != InvalidOid) + nIndexKeys++; + + /* + * Hack for non-functional btree npages estimation: npages = + * index_pages * selectivity_of_1st_attr_clause(s) - vadim 04/24/97 + */ + if (relam == BTREE_AM_OID && pgindex->indproc == InvalidOid) + nphack = true; + + npages = 0.0; + select = 1.0; + fattr_select = 1.0; - i = 0; foreach(q, indexquals) { Node *expr = (Node *) lfirst(q); + Oid opno; int dummyrelid; + AttrNumber attno; + Datum value; + int flag; + Oid indclass; + HeapTuple amopTuple; + Form_pg_amop amop; + float64 amopnpages, + amopselect; + /* + * Extract info from clause. + */ if (is_opclause(expr)) - opno_array[i] = ((Oper *) ((Expr *) expr)->oper)->opno; + opno = ((Oper *) ((Expr *) expr)->oper)->opno; else - opno_array[i] = InvalidOid; + opno = InvalidOid; + get_relattval(expr, relid, &dummyrelid, &attno, &value, &flag); - get_relattval(expr, relid, &dummyrelid, &attno_array[i], - &value_array[i], &flag_array[i]); - i++; + /* + * Find the AM class for this key. + */ + if (pgindex->indproc != InvalidOid) + { + /* + * Functional index: AM class is the first one defined since + * functional indices have exactly one key. + */ + indclass = pgindex->indclass[0]; + } + else + { + int i; + indclass = InvalidOid; + for (i = 0; pgindex->indkey[i]; i++) + { + if (attno == pgindex->indkey[i]) + { + indclass = pgindex->indclass[i]; + break; + } + } + } + if (!OidIsValid(indclass)) + { + /* + * Presumably this means that we are using a functional index + * clause and so had no variable to match to the index key ... + * if not we are in trouble. + */ + elog(NOTICE, "index_selectivity: no key %d in index %u", + attno, indexrelid); + continue; + } + + amopTuple = SearchSysCacheTuple(AMOPOPID, + ObjectIdGetDatum(indclass), + ObjectIdGetDatum(opno), + ObjectIdGetDatum(relam), + 0); + if (!HeapTupleIsValid(amopTuple)) + { + /* + * We might get here because indxpath.c selected a binary- + * compatible index. Try again with the compatible operator. + */ + if (opno != InvalidOid) + { + opno = indexable_operator((Expr *) expr, indclass, relam, + ((flag & SEL_RIGHT) != 0)); + amopTuple = SearchSysCacheTuple(AMOPOPID, + ObjectIdGetDatum(indclass), + ObjectIdGetDatum(opno), + ObjectIdGetDatum(relam), + 0); + } + if (!HeapTupleIsValid(amopTuple)) + elog(ERROR, "index_selectivity: no amop %u %u %u", + indclass, opno, relam); + } + amop = (Form_pg_amop) GETSTRUCT(amopTuple); + + if (!nphack) + { + amopnpages = (float64) fmgr(amop->amopnpages, + (char *) opno, + (char *) baserelid, + (char *) (int) attno, + (char *) value, + (char *) flag, + (char *) nIndexKeys, + (char *) indexrelid); + if (PointerIsValid(amopnpages)) + npages += *amopnpages; + } + + amopselect = (float64) fmgr(amop->amopselect, + (char *) opno, + (char *) baserelid, + (char *) (int) attno, + (char *) value, + (char *) flag, + (char *) nIndexKeys, + (char *) indexrelid); + if (PointerIsValid(amopselect)) + { + select *= *amopselect; + if (nphack && attno == pgindex->indkey[0]) + fattr_select *= *amopselect; + } } - IndexSelectivity(indexid, - getrelid(relid, root->rtable), - nclauses, - opno_array, - attno_array, - value_array, - flag_array, - idxPages, - idxSelec); - - pfree(opno_array); - pfree(attno_array); - pfree(value_array); - pfree(flag_array); + /* + * Estimation of npages below is hack of course, but it's better than + * it was before. - vadim 04/09/97 + */ + if (nphack) + { + npages = fattr_select * indexrelation->relpages; + *idxPages = (long) ceil((double) npages); + } + else + { + if (nIndexKeys > 1) + npages = npages / (1.0 + nIndexKeys); + *idxPages = (long) ceil((double) (npages / nIndexKeys)); + } + *idxSelec = select; } /* * restriction_selectivity * - * NOTE: The routine is now merged with RestrictionClauseSelectivity - * as defined in plancat.c - * * Returns the selectivity of a specified operator. * This code executes registered procedures stored in the * operator relation, by calling the function manager. @@ -279,7 +389,7 @@ index_selectivity(Query *root, * relation OIDs or attribute numbers are 0, then the clause * isn't of the form (op var const). */ -Cost +Selectivity restriction_selectivity(Oid functionObjectId, Oid operatorObjectId, Oid relationObjectId, @@ -297,28 +407,25 @@ restriction_selectivity(Oid functionObjectId, (char *) constFlag, NULL); if (!PointerIsValid(result)) - elog(ERROR, "RestrictionClauseSelectivity: bad pointer"); + elog(ERROR, "restriction_selectivity: bad pointer"); if (*result < 0.0 || *result > 1.0) - elog(ERROR, "RestrictionClauseSelectivity: bad value %lf", - *result); + elog(ERROR, "restriction_selectivity: bad value %lf", *result); - return (Cost) *result; + return (Selectivity) *result; } /* * join_selectivity - * Similarly, this routine is merged with JoinClauseSelectivity in - * plancat.c * - * Returns the selectivity of an operator, given the join clause - * information. + * Returns the selectivity of an operator, given the join clause + * information. * * XXX The assumption in the selectivity procedures is that if the * relation OIDs or attribute numbers are 0, then the clause * isn't of the form (op var var). */ -Cost +Selectivity join_selectivity(Oid functionObjectId, Oid operatorObjectId, Oid relationObjectId1, @@ -336,13 +443,12 @@ join_selectivity(Oid functionObjectId, (char *) (int) attributeNumber2, NULL); if (!PointerIsValid(result)) - elog(ERROR, "JoinClauseSelectivity: bad pointer"); + elog(ERROR, "join_selectivity: bad pointer"); if (*result < 0.0 || *result > 1.0) - elog(ERROR, "JoinClauseSelectivity: bad value %lf", - *result); + elog(ERROR, "join_selectivity: bad value %lf", *result); - return (Cost) *result; + return (Selectivity) *result; } /* @@ -421,172 +527,3 @@ VersionGetParents(Oid verrelid) } #endif - - -/***************************************************************************** - * - *****************************************************************************/ - -/* - * IndexSelectivity - * - * Calls the 'amopnpages' and 'amopselect' functions for each - * AM operator when a given index (specified by 'indexrelid') is used. - * The total number of pages and product of the selectivities are returned. - * - * Assumption: the attribute numbers and operator ObjectIds are in order - * WRT to each other (otherwise, you have no way of knowing which - * AM operator class or attribute number corresponds to which operator. - * - * 'nIndexKeys' is the number of qual clauses in use - * 'varAttributeNumbers' contains attribute numbers for variables - * 'constValues' contains the constant values - * 'constFlags' describes how to treat the constants in each clause - */ -static void -IndexSelectivity(Oid indexrelid, - Oid baserelid, - int nIndexKeys, - Oid *operatorObjectIds, - AttrNumber *varAttributeNumbers, - Datum *constValues, - int *constFlags, - float *idxPages, - float *idxSelec) -{ - int i, - n; - HeapTuple indexTuple, - amopTuple, - indRel; - Form_pg_class indexrelation; - Form_pg_index index; - Form_pg_amop amop; - Oid indclass; - float64data npages, - select; - float64 amopnpages, - amopselect; - Oid relam; - bool nphack = false; - float64data fattr_select = 1.0; - - indRel = SearchSysCacheTuple(RELOID, - ObjectIdGetDatum(indexrelid), - 0, 0, 0); - if (!HeapTupleIsValid(indRel)) - elog(ERROR, "IndexSelectivity: index %u not found", - indexrelid); - indexrelation = (Form_pg_class) GETSTRUCT(indRel); - relam = indexrelation->relam; - - indexTuple = SearchSysCacheTuple(INDEXRELID, - ObjectIdGetDatum(indexrelid), - 0, 0, 0); - if (!HeapTupleIsValid(indexTuple)) - elog(ERROR, "IndexSelectivity: index %u not found", - indexrelid); - index = (Form_pg_index) GETSTRUCT(indexTuple); - - /* - * Hack for non-functional btree npages estimation: npages = - * index_pages * selectivity_of_1st_attr_clause(s) - vadim 04/24/97 - */ - if (relam == BTREE_AM_OID && - varAttributeNumbers[0] != InvalidAttrNumber) - nphack = true; - - npages = 0.0; - select = 1.0; - for (n = 0; n < nIndexKeys; n++) - { - /* - * Find the AM class for this key. - * - * If the first attribute number is invalid then we have a functional - * index, and AM class is the first one defined since functional - * indices have exactly one key. - */ - indclass = (varAttributeNumbers[0] == InvalidAttrNumber) ? - index->indclass[0] : InvalidOid; - i = 0; - while ((i < nIndexKeys) && (indclass == InvalidOid)) - { - if (varAttributeNumbers[n] == index->indkey[i]) - { - indclass = index->indclass[i]; - break; - } - i++; - } - if (!OidIsValid(indclass)) - { - - /* - * Presumably this means that we are using a functional index - * clause and so had no variable to match to the index key ... - * if not we are in trouble. - */ - elog(NOTICE, "IndexSelectivity: no key %d in index %u", - varAttributeNumbers[n], indexrelid); - continue; - } - - amopTuple = SearchSysCacheTuple(AMOPOPID, - ObjectIdGetDatum(indclass), - ObjectIdGetDatum(operatorObjectIds[n]), - ObjectIdGetDatum(relam), - 0); - if (!HeapTupleIsValid(amopTuple)) - elog(ERROR, "IndexSelectivity: no amop %u %u %u", - indclass, operatorObjectIds[n], relam); - amop = (Form_pg_amop) GETSTRUCT(amopTuple); - - if (!nphack) - { - amopnpages = (float64) fmgr(amop->amopnpages, - (char *) operatorObjectIds[n], - (char *) baserelid, - (char *) (int) varAttributeNumbers[n], - (char *) constValues[n], - (char *) constFlags[n], - (char *) nIndexKeys, - (char *) indexrelid); - if (PointerIsValid(amopnpages)) - npages += *amopnpages; - } - - amopselect = (float64) fmgr(amop->amopselect, - (char *) operatorObjectIds[n], - (char *) baserelid, - (char *) (int) varAttributeNumbers[n], - (char *) constValues[n], - (char *) constFlags[n], - (char *) nIndexKeys, - (char *) indexrelid); - - if (PointerIsValid(amopselect)) - { - select *= *amopselect; - if (nphack && varAttributeNumbers[n] == index->indkey[0]) - fattr_select *= *amopselect; - } - } - - /* - * Estimation of npages below is hack of course, but it's better than - * it was before. - vadim 04/09/97 - */ - if (nphack) - { - npages = fattr_select * indexrelation->relpages; - *idxPages = ceil((double) npages); - } - else - { - if (nIndexKeys > 1) - npages = npages / (1.0 + nIndexKeys); - *idxPages = ceil((double) (npages / nIndexKeys)); - } - *idxSelec = select; -} diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c index 885d0f0715c..bb6773dfe1b 100644 --- a/src/backend/optimizer/util/relnode.c +++ b/src/backend/optimizer/util/relnode.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.19 1999/08/16 02:17:58 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.20 2000/01/09 00:26:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -37,21 +37,15 @@ get_base_rel(Query *root, int relid) { rel = makeNode(RelOptInfo); rel->relids = relids; - rel->indexed = false; - rel->pages = 0; - rel->tuples = 0; - rel->size = 0; + rel->rows = 0; rel->width = 0; rel->targetlist = NIL; rel->pathlist = NIL; rel->cheapestpath = (Path *) NULL; rel->pruneable = true; - rel->classlist = NULL; - rel->indexkeys = NULL; - rel->ordering = NULL; - rel->relam = InvalidOid; - rel->indproc = InvalidOid; - rel->indpred = NIL; + rel->indexed = false; + rel->pages = 0; + rel->tuples = 0; rel->restrictinfo = NIL; rel->joininfo = NIL; rel->innerjoin = NIL; |