Server Configuration
When this parameter is on>, the planner compares
query conditions with table CHECK> constraints, and
omits scanning tables for which the conditions contradict the
- constraints. (Presently this is done only for child tables of
- inheritance scans.) For example:
+ constraints. For example:
CREATE TABLE parent(key integer, ...);
-
+
Data Definition
PostgreSQL supports basic table
- partitioning. This section describes why and how you can implement
+ partitioning. This section describes why and how to implement
partitioning as part of your database design.
table of a single parent table. The parent table itself is normally
empty; it exists just to represent the entire data set. You should be
familiar with inheritance (see ) before
- attempting to implement partitioning.
+ attempting to set up partitioning.
UNION ALL SELECT * FROM measurement_yy06mm01;
- However, constraint exclusion is currently not supported for
- partitioned tables defined in this manner. Also, the need to
+ However, the need to
recreate the view adds an extra step to adding and dropping
individual partitions of the dataset.
optimized, since the planner cannot know what partitions the
parameter value might select at runtime. For the same reason,
stable> functions such as CURRENT_DATE
- must be avoided. Joining the partition key to a column of another
- table will not be optimized, either.
+ must be avoided.
-
- UPDATE and DELETE commands
- against the master table do not currently perform constraint exclusion.
-
-
-
All constraints on all partitions of the master table are considered for
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.141 2006/02/03 21:08:49 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.142 2006/02/04 23:03:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "optimizer/paths.h"
#include "optimizer/plancat.h"
#include "optimizer/planner.h"
-#include "optimizer/predtest.h"
#include "optimizer/prep.h"
#include "optimizer/var.h"
#include "parser/parsetree.h"
/* These parameters are set by GUC */
-bool constraint_exclusion = false;
bool enable_geqo = false; /* just in case GUC doesn't set it */
int geqo_threshold;
static void set_base_rel_pathlists(PlannerInfo *root);
-static void set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
- Index rti, RangeTblEntry *rte);
+static void set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, Index rti);
static void set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
RangeTblEntry *rte);
static void set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
if (rel->reloptkind != RELOPT_BASEREL)
continue;
- set_rel_pathlist(root, rel, rti,
- rt_fetch(rti, root->parse->rtable));
+ set_rel_pathlist(root, rel, rti);
}
}
* Build access paths for a base relation
*/
static void
-set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
- Index rti, RangeTblEntry *rte)
+set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, Index rti)
{
+ RangeTblEntry *rte = rt_fetch(rti, root->parse->rtable);
+
if (rte->inh)
{
/* It's an "append relation", process accordingly */
if (create_or_index_quals(root, rel))
set_baserel_size_estimates(root, rel);
+ /*
+ * If we can prove we don't need to scan the rel via constraint exclusion,
+ * set up a single dummy path for it. (Rather than inventing a special
+ * "dummy" path type, we represent this as an AppendPath with no members.)
+ */
+ if (relation_excluded_by_constraints(rel, rte))
+ {
+ /* Reset output-rows estimate to 0 */
+ rel->rows = 0;
+
+ add_path(rel, (Path *) create_append_path(rel, NIL));
+
+ /* Select cheapest path (pretty easy in this case...) */
+ set_cheapest(rel);
+
+ return;
+ }
+
/*
* Generate paths and add them to the rel's pathlist.
*
AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
int childRTindex;
RelOptInfo *childrel;
- RangeTblEntry *childrte;
Path *childpath;
ListCell *parentvars;
ListCell *childvars;
childrel->max_attr);
/*
- * If we can prove we don't need to scan this child via constraint
- * exclusion, just ignore it. (We have to have converted the
- * baserestrictinfo Vars before we can make the test.)
- *
- * XXX it'd probably be better to give the child some kind of dummy
- * cheapest path, or otherwise explicitly mark it as ignorable.
- * Currently there is an ugly check in join_before_append() to handle
- * excluded children.
- */
- childrte = rt_fetch(childRTindex, root->parse->rtable);
- if (constraint_exclusion &&
- childrte->rtekind == RTE_RELATION)
- {
- List *constraint_pred;
-
- constraint_pred = get_relation_constraints(childrte->relid,
- childrel);
-
- /*
- * We do not currently enforce that CHECK constraints contain only
- * immutable functions, so it's necessary to check here. We
- * daren't draw conclusions from plan-time evaluation of
- * non-immutable functions.
- */
- if (!contain_mutable_functions((Node *) constraint_pred))
- {
- /*
- * The constraints are effectively ANDed together, so we can
- * just try to refute the entire collection at once. This may
- * allow us to make proofs that would fail if we took them
- * individually.
- */
- if (predicate_refuted_by(constraint_pred,
- childrel->baserestrictinfo))
- continue;
- }
- }
-
- /*
- * Compute the child's access paths, and save the cheapest.
+ * Compute the child's access paths, and add the cheapest one
+ * to the Append path we are constructing for the parent.
*
* It's possible that the child is itself an appendrel, in which
* case we can "cut out the middleman" and just add its child
* paths to our own list. (We don't try to do this earlier because
* we need to apply both levels of transformation to the quals.)
+ * This test also handles the case where the child rel need not
+ * be scanned because of constraint exclusion: it'll have an
+ * Append path with no subpaths, and will vanish from our list.
*/
- set_rel_pathlist(root, childrel, childRTindex, childrte);
+ set_rel_pathlist(root, childrel, childRTindex);
childpath = childrel->cheapest_total_path;
if (IsA(childpath, AppendPath))
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.100 2006/02/03 21:08:49 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.101 2006/02/04 23:03:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
Assert(childrel->reloptkind == RELOPT_OTHER_MEMBER_REL);
/*
- * If the child has no cheapest_total_path, assume it was deemed
- * excludable by constraint exclusion (see set_append_rel_pathlist).
+ * Check to see if child was rejected by constraint exclusion.
+ * If so, it will have a cheapest_total_path that's an Append path
+ * with no members (see set_plain_rel_pathlist).
*/
- if (childrel->cheapest_total_path == NULL)
- {
- Assert(constraint_exclusion);
- continue;
- }
+ if (IsA(childrel->cheapest_total_path, AppendPath) &&
+ ((AppendPath *) childrel->cheapest_total_path)->subpaths == NIL)
+ continue; /* OK, we can ignore it */
/*
* Get the best innerjoin indexpath (if any) for this outer rel.
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.117 2006/01/31 21:39:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.118 2006/02/04 23:03:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "nodes/makefuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/plancat.h"
+#include "optimizer/predtest.h"
#include "optimizer/prep.h"
#include "optimizer/tlist.h"
#include "parser/parsetree.h"
#include "miscadmin.h"
+/* GUC parameter */
+bool constraint_exclusion = false;
+
+
static void estimate_rel_size(Relation rel, int32 *attr_widths,
BlockNumber *pages, double *tuples);
+static List *get_relation_constraints(Oid relationObjectId, RelOptInfo *rel);
/*
* run, and in many cases it won't be invoked at all, so there seems no
* point in caching the data in RelOptInfo.
*/
-List *
+static List *
get_relation_constraints(Oid relationObjectId, RelOptInfo *rel)
{
List *result = NIL;
}
+/*
+ * relation_excluded_by_constraints
+ *
+ * Detect whether the relation need not be scanned because it has CHECK
+ * constraints that conflict with the query's WHERE clause.
+ */
+bool
+relation_excluded_by_constraints(RelOptInfo *rel, RangeTblEntry *rte)
+{
+ List *constraint_pred;
+
+ /* Skip the test if constraint exclusion is disabled */
+ if (!constraint_exclusion)
+ return false;
+
+ /* Only plain relations have constraints */
+ if (rte->rtekind != RTE_RELATION || rte->inh)
+ return false;
+
+ /* OK to fetch the constraint expressions */
+ constraint_pred = get_relation_constraints(rte->relid, rel);
+
+ /*
+ * We do not currently enforce that CHECK constraints contain only
+ * immutable functions, so it's necessary to check here. We daren't draw
+ * conclusions from plan-time evaluation of non-immutable functions.
+ */
+ if (contain_mutable_functions((Node *) constraint_pred))
+ return false;
+
+ /*
+ * The constraints are effectively ANDed together, so we can just try to
+ * refute the entire collection at once. This may allow us to make proofs
+ * that would fail if we took them individually.
+ */
+ if (predicate_refuted_by(constraint_pred, rel->baserestrictinfo))
+ return true;
+
+ return false;
+}
+
+
/*
* build_physical_tlist
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/optimizer/plancat.h,v 1.37 2005/07/23 21:05:48 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/plancat.h,v 1.38 2006/02/04 23:03:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern void get_relation_info(Oid relationObjectId, RelOptInfo *rel);
-extern List *get_relation_constraints(Oid relationObjectId, RelOptInfo *rel);
+extern bool relation_excluded_by_constraints(RelOptInfo *rel,
+ RangeTblEntry *rte);
extern List *build_physical_tlist(PlannerInfo *root, RelOptInfo *rel);