summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/path/costsize.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2006-07-01 18:38:33 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2006-07-01 18:38:33 +0000
commitcffd89ca736e485309cd51ae056f837bd7e683ad (patch)
tree7ebf13ae5d921d074382d80be66a8d97e7a822e1 /src/backend/optimizer/path/costsize.c
parent68628fc38ea7a3c72f6a813b0193d836731d9c10 (diff)
downloadpostgresql-cffd89ca736e485309cd51ae056f837bd7e683ad.tar.gz
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause can be used as a one-time qual in a gating Result plan node, to suppress plan execution entirely when it is false. Even when the clause is true, putting it in a gating node wins by avoiding repeated evaluation of the clause. In previous PG releases, query_planner() would do this for pseudoconstant clauses appearing at the top level of the jointree, but there was no ability to generate a gating Result deeper in the plan tree. To fix it, get rid of the special case in query_planner(), and instead process pseudoconstant clauses through the normal RestrictInfo qual distribution mechanism. When a pseudoconstant clause is found attached to a path node in create_plan(), pull it out and generate a gating Result at that point. This requires special-casing pseudoconstants in selectivity estimation and cost_qual_eval, but on the whole it's pretty clean. It probably even makes the planner a bit faster than before for the normal case of no pseudoconstants, since removing pull_constant_clauses saves one useless traversal of the qual tree. Per gripe from Phil Frost.
Diffstat (limited to 'src/backend/optimizer/path/costsize.c')
-rw-r--r--src/backend/optimizer/path/costsize.c31
1 files changed, 21 insertions, 10 deletions
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index fa8d06707b..eec165ab5d 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -54,7 +54,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.158 2006/06/06 17:59:57 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.159 2006/07/01 18:38:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1604,20 +1604,29 @@ cost_qual_eval(QualCost *cost, List *quals)
* routine's use, so that it's not necessary to evaluate the qual
* clause's cost more than once. If the clause's cost hasn't been
* computed yet, the field's startup value will contain -1.
+ *
+ * If the RestrictInfo is marked pseudoconstant, it will be tested
+ * only once, so treat its cost as all startup cost.
*/
if (qual && IsA(qual, RestrictInfo))
{
- RestrictInfo *restrictinfo = (RestrictInfo *) qual;
+ RestrictInfo *rinfo = (RestrictInfo *) qual;
- if (restrictinfo->eval_cost.startup < 0)
+ if (rinfo->eval_cost.startup < 0)
{
- restrictinfo->eval_cost.startup = 0;
- restrictinfo->eval_cost.per_tuple = 0;
- cost_qual_eval_walker((Node *) restrictinfo->clause,
- &restrictinfo->eval_cost);
+ rinfo->eval_cost.startup = 0;
+ rinfo->eval_cost.per_tuple = 0;
+ cost_qual_eval_walker((Node *) rinfo->clause,
+ &rinfo->eval_cost);
+ if (rinfo->pseudoconstant)
+ {
+ /* count one execution during startup */
+ rinfo->eval_cost.startup += rinfo->eval_cost.per_tuple;
+ rinfo->eval_cost.per_tuple = 0;
+ }
}
- cost->startup += restrictinfo->eval_cost.startup;
- cost->per_tuple += restrictinfo->eval_cost.per_tuple;
+ cost->startup += rinfo->eval_cost.startup;
+ cost->per_tuple += rinfo->eval_cost.per_tuple;
}
else
{
@@ -1876,7 +1885,9 @@ set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel,
*
* If we are doing an outer join, take that into account: the output must
* be at least as large as the non-nullable input. (Is there any chance
- * of being even smarter?)
+ * of being even smarter?) (XXX this is not really right, because it
+ * assumes all the restriction clauses are join clauses; we should figure
+ * pushed-down clauses separately.)
*
* For JOIN_IN and variants, the Cartesian product is figured with respect
* to a unique-ified input, and then we can clamp to the size of the other