diff options
| author | Tom Lane <tgl@sss.pgh.pa.us> | 2006-07-01 18:38:33 +0000 |
|---|---|---|
| committer | Tom Lane <tgl@sss.pgh.pa.us> | 2006-07-01 18:38:33 +0000 |
| commit | cffd89ca736e485309cd51ae056f837bd7e683ad (patch) | |
| tree | 7ebf13ae5d921d074382d80be66a8d97e7a822e1 /src/backend/optimizer/path/costsize.c | |
| parent | 68628fc38ea7a3c72f6a813b0193d836731d9c10 (diff) | |
| download | postgresql-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.c | 31 |
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 |
