1 /*-------------------------------------------------------------------------
4 * Routines to compute clause selectivities
6 * Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.28 2000/01/23 02:06:58 tgl Exp $
12 *-------------------------------------------------------------------------
16 #include "catalog/pg_operator.h"
17 #include "optimizer/clauses.h"
18 #include "optimizer/cost.h"
19 #include "optimizer/internal.h"
20 #include "optimizer/plancat.h"
21 #include "optimizer/restrictinfo.h"
22 #include "parser/parsetree.h"
23 #include "utils/lsyscache.h"
26 /****************************************************************************
27 * ROUTINES TO COMPUTE SELECTIVITIES
28 ****************************************************************************/
31 * restrictlist_selectivity -
32 * Compute the selectivity of an implicitly-ANDed list of RestrictInfo
35 * This is the same as clauselist_selectivity except for the representation
39 restrictlist_selectivity(Query *root,
40 List *restrictinfo_list,
43 List *clauselist = get_actual_clauses(restrictinfo_list);
46 result = clauselist_selectivity(root, clauselist, varRelid);
52 * clauselist_selectivity -
53 * Compute the selectivity of an implicitly-ANDed list of boolean
54 * expression clauses. The list can be empty, in which case 1.0
57 * See clause_selectivity() for the meaning of the varRelid parameter.
60 clauselist_selectivity(Query *root,
67 /* Use the product of the selectivities of the subclauses.
68 * XXX this is too optimistic, since the subclauses
69 * are very likely not independent...
71 foreach(clause, clauses)
73 Selectivity s2 = clause_selectivity(root,
74 (Node *) lfirst(clause),
82 * clause_selectivity -
83 * Compute the selectivity of a general boolean expression clause.
85 * varRelid is either 0 or a rangetable index.
87 * When varRelid is not 0, only variables belonging to that relation are
88 * considered in computing selectivity; other vars are treated as constants
89 * of unknown values. This is appropriate for estimating the selectivity of
90 * a join clause that is being used as a restriction clause in a scan of a
91 * nestloop join's inner relation --- varRelid should then be the ID of the
94 * When varRelid is 0, all variables are treated as variables. This
95 * is appropriate for ordinary join clauses and restriction clauses.
98 clause_selectivity(Query *root,
102 Selectivity s1 = 1.0; /* default for any unhandled clause type */
106 if (IsA(clause, Var))
109 * we have a bool Var. This is exactly equivalent to the clause:
110 * reln.attribute = 't' so we compute the selectivity as if that
111 * is what we have. The magic #define constants are a hack. I
112 * didn't want to have to do system cache look ups to find out all
115 Index varno = ((Var *) clause)->varno;
117 if (varRelid == 0 || varRelid == varno)
118 s1 = restriction_selectivity(F_EQSEL,
119 BooleanEqualOperator,
120 getrelid(varno, root->rtable),
121 ((Var *) clause)->varattno,
123 SEL_CONSTANT | SEL_RIGHT);
124 /* an outer-relation bool var is taken as always true... */
126 else if (IsA(clause, Param))
128 /* XXX any way to do better? */
131 else if (IsA(clause, Const))
133 /* bool constant is pretty easy... */
134 s1 = ((bool) ((Const *) clause)->constvalue) ? 1.0 : 0.0;
136 else if (not_clause(clause))
138 /* inverse of the selectivity of the underlying clause */
139 s1 = 1.0 - clause_selectivity(root,
140 (Node*) get_notclausearg((Expr*) clause),
143 else if (and_clause(clause))
145 /* share code with clauselist_selectivity() */
146 s1 = clauselist_selectivity(root,
147 ((Expr *) clause)->args,
150 else if (or_clause(clause))
153 * Selectivities for an 'or' clause are computed as s1+s2 - s1*s2
154 * to account for the probable overlap of selected tuple sets.
155 * XXX is this too conservative?
159 foreach(arg, ((Expr *) clause)->args)
161 Selectivity s2 = clause_selectivity(root,
162 (Node *) lfirst(arg),
164 s1 = s1 + s2 - s1 * s2;
167 else if (is_opclause(clause))
169 Oid opno = ((Oper *) ((Expr *) clause)->oper)->opno;
175 * If we are considering a nestloop join then all clauses
176 * are restriction clauses, since we are only interested in
179 is_join_clause = false;
184 * Otherwise, it's a join if there's more than one relation used.
186 is_join_clause = (NumRelids(clause) > 1);
191 /* Estimate selectivity for a join clause. */
192 RegProcedure oprjoin = get_oprjoin(opno);
195 * if the oprjoin procedure is missing for whatever reason, use a
199 s1 = (Selectivity) 0.5;
209 get_rels_atts(clause, &relid1, &attno1, &relid2, &attno2);
210 reloid1 = relid1 ? getrelid(relid1, root->rtable) : InvalidOid;
211 reloid2 = relid2 ? getrelid(relid2, root->rtable) : InvalidOid;
212 s1 = join_selectivity(oprjoin, opno,
219 /* Estimate selectivity for a restriction clause. */
220 RegProcedure oprrest = get_oprrest(opno);
223 * if the oprrest procedure is missing for whatever reason, use a
227 s1 = (Selectivity) 0.5;
236 get_relattval(clause, varRelid,
237 &relidx, &attno, &constval, &flag);
238 reloid = relidx ? getrelid(relidx, root->rtable) : InvalidOid;
239 s1 = restriction_selectivity(oprrest, opno,
245 else if (is_funcclause(clause))
248 * This is not an operator, so we guess at the selectivity. THIS
249 * IS A HACK TO GET V4 OUT THE DOOR. FUNCS SHOULD BE ABLE TO HAVE
250 * SELECTIVITIES THEMSELVES. -- JMH 7/9/92
252 s1 = (Selectivity) 0.3333333;
254 else if (is_subplan(clause))
257 * Just for the moment! FIX ME! - vadim 02/04/98