/*-------------------------------------------------------------------------
*
* clausesel.c
- * Routines to compute and set clause selectivities
+ * Routines to compute clause selectivities
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.27 2000/01/09 00:26:31 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.28 2000/01/23 02:06:58 tgl Exp $
*
*-------------------------------------------------------------------------
*/
****************************************************************************/
/*
- * restrictlist_selec -
+ * restrictlist_selectivity -
* Compute the selectivity of an implicitly-ANDed list of RestrictInfo
* clauses.
*
- * This is the same as clauselist_selec except for the form of the input.
+ * This is the same as clauselist_selectivity except for the representation
+ * of the clause list.
*/
Selectivity
-restrictlist_selec(Query *root, List *restrictinfo_list)
+restrictlist_selectivity(Query *root,
+ List *restrictinfo_list,
+ int varRelid)
{
List *clauselist = get_actual_clauses(restrictinfo_list);
Selectivity result;
- result = clauselist_selec(root, clauselist);
+ result = clauselist_selectivity(root, clauselist, varRelid);
freeList(clauselist);
return result;
}
/*
- * clauselist_selec -
+ * clauselist_selectivity -
* Compute the selectivity of an implicitly-ANDed list of boolean
- * expression clauses.
+ * expression clauses. The list can be empty, in which case 1.0
+ * must be returned.
+ *
+ * See clause_selectivity() for the meaning of the varRelid parameter.
*/
Selectivity
-clauselist_selec(Query *root, List *clauses)
+clauselist_selectivity(Query *root,
+ List *clauses,
+ int varRelid)
{
Selectivity s1 = 1.0;
List *clause;
/* Use the product of the selectivities of the subclauses.
- * XXX this is probably too optimistic, since the subclauses
+ * XXX this is too optimistic, since the subclauses
* are very likely not independent...
*/
foreach(clause, clauses)
{
- Selectivity s2 = compute_clause_selec(root, (Node *) lfirst(clause));
+ Selectivity s2 = clause_selectivity(root,
+ (Node *) lfirst(clause),
+ varRelid);
s1 = s1 * s2;
}
return s1;
}
/*
- * compute_clause_selec -
+ * clause_selectivity -
* Compute the selectivity of a general boolean expression clause.
+ *
+ * varRelid is either 0 or a rangetable index.
+ *
+ * When varRelid is not 0, only variables belonging to that relation are
+ * considered in computing selectivity; other vars are treated as constants
+ * of unknown values. This is appropriate for estimating the selectivity of
+ * a join clause that is being used as a restriction clause in a scan of a
+ * nestloop join's inner relation --- varRelid should then be the ID of the
+ * inner relation.
+ *
+ * When varRelid is 0, all variables are treated as variables. This
+ * is appropriate for ordinary join clauses and restriction clauses.
*/
Selectivity
-compute_clause_selec(Query *root, Node *clause)
+clause_selectivity(Query *root,
+ Node *clause,
+ int varRelid)
{
Selectivity s1 = 1.0; /* default for any unhandled clause type */
* didn't want to have to do system cache look ups to find out all
* of that info.
*/
- s1 = restriction_selectivity(F_EQSEL,
- BooleanEqualOperator,
- getrelid(((Var *) clause)->varno,
- root->rtable),
- ((Var *) clause)->varattno,
- Int8GetDatum(true),
- SEL_CONSTANT | SEL_RIGHT);
+ Index varno = ((Var *) clause)->varno;
+
+ if (varRelid == 0 || varRelid == varno)
+ s1 = restriction_selectivity(F_EQSEL,
+ BooleanEqualOperator,
+ getrelid(varno, root->rtable),
+ ((Var *) clause)->varattno,
+ Int8GetDatum(true),
+ SEL_CONSTANT | SEL_RIGHT);
+ /* an outer-relation bool var is taken as always true... */
}
else if (IsA(clause, Param))
{
else if (not_clause(clause))
{
/* inverse of the selectivity of the underlying clause */
- s1 = 1.0 - compute_clause_selec(root,
- (Node *) get_notclausearg((Expr *) clause));
+ s1 = 1.0 - clause_selectivity(root,
+ (Node*) get_notclausearg((Expr*) clause),
+ varRelid);
}
else if (and_clause(clause))
{
- s1 = clauselist_selec(root, ((Expr *) clause)->args);
+ /* share code with clauselist_selectivity() */
+ s1 = clauselist_selectivity(root,
+ ((Expr *) clause)->args,
+ varRelid);
}
else if (or_clause(clause))
{
s1 = 0.0;
foreach(arg, ((Expr *) clause)->args)
{
- Selectivity s2 = compute_clause_selec(root, (Node *) lfirst(arg));
+ Selectivity s2 = clause_selectivity(root,
+ (Node *) lfirst(arg),
+ varRelid);
s1 = s1 + s2 - s1 * s2;
}
}
else if (is_opclause(clause))
{
- if (NumRelids(clause) == 1)
- {
- /* The opclause is not a join clause, since there is only one
- * relid in the clause. The clause selectivity will be based on
- * the operator selectivity and operand values.
- */
- Oid opno = ((Oper *) ((Expr *) clause)->oper)->opno;
- RegProcedure oprrest = get_oprrest(opno);
+ Oid opno = ((Oper *) ((Expr *) clause)->oper)->opno;
+ bool is_join_clause;
+ if (varRelid != 0)
+ {
/*
- * if the oprrest procedure is missing for whatever reason, use a
- * selectivity of 0.5
+ * If we are considering a nestloop join then all clauses
+ * are restriction clauses, since we are only interested in
+ * the one relation.
*/
- if (!oprrest)
- s1 = (Selectivity) 0.5;
- else
- {
- int relidx;
- AttrNumber attno;
- Datum constval;
- int flag;
- Oid reloid;
-
- get_relattval(clause, 0, &relidx, &attno, &constval, &flag);
- reloid = relidx ? getrelid(relidx, root->rtable) : InvalidOid;
- s1 = restriction_selectivity(oprrest, opno,
- reloid, attno,
- constval, flag);
- }
+ is_join_clause = false;
}
else
{
/*
- * The clause must be a join clause. The clause selectivity will
- * be based on the relations to be scanned and the attributes they
- * are to be joined on.
+ * Otherwise, it's a join if there's more than one relation used.
*/
- Oid opno = ((Oper *) ((Expr *) clause)->oper)->opno;
+ is_join_clause = (NumRelids(clause) > 1);
+ }
+
+ if (is_join_clause)
+ {
+ /* Estimate selectivity for a join clause. */
RegProcedure oprjoin = get_oprjoin(opno);
/*
reloid2, attno2);
}
}
+ else
+ {
+ /* Estimate selectivity for a restriction clause. */
+ RegProcedure oprrest = get_oprrest(opno);
+
+ /*
+ * if the oprrest procedure is missing for whatever reason, use a
+ * selectivity of 0.5
+ */
+ if (!oprrest)
+ s1 = (Selectivity) 0.5;
+ else
+ {
+ int relidx;
+ AttrNumber attno;
+ Datum constval;
+ int flag;
+ Oid reloid;
+
+ get_relattval(clause, varRelid,
+ &relidx, &attno, &constval, &flag);
+ reloid = relidx ? getrelid(relidx, root->rtable) : InvalidOid;
+ s1 = restriction_selectivity(oprrest, opno,
+ reloid, attno,
+ constval, flag);
+ }
+ }
}
else if (is_funcclause(clause))
{
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.79 2000/01/15 02:59:30 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.80 2000/01/23 02:07:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
List *scan_clauses)
{
List *indxqual = best_path->indexqual;
+ Index baserelid;
List *qpqual;
List *fixed_indxqual;
List *ixid;
/* there should be exactly one base rel involved... */
Assert(length(best_path->path.parent->relids) == 1);
+ baserelid = lfirsti(best_path->path.parent->relids);
/* check to see if any of the indices are lossy */
foreach(ixid, best_path->indexid)
{
/* recompute output row estimate using all available quals */
plan_rows = best_path->path.parent->tuples *
- clauselist_selec(root, lcons(indxqual_expr, qpqual));
+ clauselist_selectivity(root,
+ lcons(indxqual_expr, qpqual),
+ baserelid);
}
if (lossy)
{
/* recompute output row estimate using all available quals */
plan_rows = best_path->path.parent->tuples *
- clauselist_selec(root, nconc(listCopy(indxqual_list), qpqual));
+ clauselist_selectivity(root,
+ nconc(listCopy(indxqual_list), qpqual),
+ baserelid);
}
if (lossy)
scan_node = make_indexscan(tlist,
qpqual,
- lfirsti(best_path->path.parent->relids),
+ baserelid,
best_path->indexid,
fixed_indxqual,
indxqual);
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: cost.h,v 1.26 2000/01/22 23:50:26 tgl Exp $
+ * $Id: cost.h,v 1.27 2000/01/23 02:06:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "nodes/relation.h"
+/* defaults for costsize.c's Cost parameters */
+/* NB: cost-estimation code should use the variables, not the constants! */
+#define CPU_PAGE_WEIGHT 0.033
+#define CPU_INDEX_PAGE_WEIGHT 0.017
+
/* defaults for function attributes used for expensive function calculations */
#define BYTE_PCT 100
#define PERBYTE_CPU 0
#define PERCALL_CPU 0
#define OUTIN_RATIO 100
-/* defaults for costsize.c's Cost parameters */
-/* NB: cost-estimation code should use the variables, not the constants! */
-#define CPU_PAGE_WEIGHT 0.033
-#define CPU_INDEX_PAGE_WEIGHT 0.017
/*
* prototypes for clausesel.c
* routines to compute clause selectivities
*/
-extern Selectivity restrictlist_selec(Query *root, List *restrictinfo_list);
-extern Selectivity clauselist_selec(Query *root, List *clauses);
-extern Selectivity compute_clause_selec(Query *root, Node *clause);
+extern Selectivity restrictlist_selectivity(Query *root,
+ List *restrictinfo_list,
+ int varRelid);
+extern Selectivity clauselist_selectivity(Query *root,
+ List *clauses,
+ int varRelid);
+extern Selectivity clause_selectivity(Query *root,
+ Node *clause,
+ int varRelid);
#endif /* COST_H */