1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-21 00:42:43 +03:00

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.
This commit is contained in:
Tom Lane
2006-07-01 18:38:33 +00:00
parent 68628fc38e
commit cffd89ca73
20 changed files with 464 additions and 294 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.79 2006/03/07 01:00:15 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.80 2006/07/01 18:38:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -117,10 +117,18 @@ clauselist_selectivity(PlannerInfo *root,
/*
* Check for being passed a RestrictInfo.
*
* If it's a pseudoconstant RestrictInfo, then s2 is either 1.0 or
* 0.0; just use that rather than looking for range pairs.
*/
if (IsA(clause, RestrictInfo))
{
rinfo = (RestrictInfo *) clause;
if (rinfo->pseudoconstant)
{
s1 = s1 * s2;
continue;
}
clause = (Node *) rinfo->clause;
}
else
@@ -422,6 +430,20 @@ clause_selectivity(PlannerInfo *root,
{
rinfo = (RestrictInfo *) clause;
/*
* If the clause is marked pseudoconstant, then it will be used as
* a gating qual and should not affect selectivity estimates; hence
* return 1.0. The only exception is that a constant FALSE may
* be taken as having selectivity 0.0, since it will surely mean
* no rows out of the plan. This case is simple enough that we
* need not bother caching the result.
*/
if (rinfo->pseudoconstant)
{
if (! IsA(rinfo->clause, Const))
return s1;
}
/*
* If possible, cache the result of the selectivity calculation for
* the clause. We can cache if varRelid is zero or the clause
@@ -509,7 +531,10 @@ clause_selectivity(PlannerInfo *root,
else if (IsA(clause, Const))
{
/* bool constant is pretty easy... */
s1 = ((bool) ((Const *) clause)->constvalue) ? 1.0 : 0.0;
Const *con = (Const *) clause;
s1 = con->constisnull ? 0.0 :
DatumGetBool(con->constvalue) ? 1.0 : 0.0;
}
else if (IsA(clause, Param))
{
@@ -519,7 +544,10 @@ clause_selectivity(PlannerInfo *root,
if (IsA(subst, Const))
{
/* bool constant is pretty easy... */
s1 = ((bool) ((Const *) subst)->constvalue) ? 1.0 : 0.0;
Const *con = (Const *) subst;
s1 = con->constisnull ? 0.0 :
DatumGetBool(con->constvalue) ? 1.0 : 0.0;
}
else
{