]> granicus.if.org Git - postgresql/commitdiff
Create a third option named "partition" for constraint_exclusion, and make it
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 7 Jan 2009 22:40:49 +0000 (22:40 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 7 Jan 2009 22:40:49 +0000 (22:40 +0000)
the default.  This setting enables constraint exclusion checks only for
appendrel members (ie, inheritance children and UNION ALL arms), which are
the cases in which constraint exclusion is most likely to be useful.  Avoiding
the overhead for simple queries that are unlikely to benefit should bring
the cost down to the point where this is a reasonable default setting.
Per today's discussion.

doc/src/sgml/config.sgml
doc/src/sgml/ddl.sgml
doc/src/sgml/textsearch.sgml
src/backend/optimizer/util/plancat.c
src/backend/utils/misc/guc.c
src/backend/utils/misc/postgresql.conf.sample
src/include/optimizer/cost.h

index ac30c510f2473b937f4cd102a078e6e0e15fddb2..564e5c0236c854ca4cc323a8d74e7423304b81a6 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.202 2009/01/07 12:21:47 mha Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.203 2009/01/07 22:40:48 tgl Exp $ -->
 
 <chapter Id="runtime-config">
   <title>Server Configuration</title>
@@ -2145,7 +2145,7 @@ archive_command = 'copy "%p" "C:\\server\\archivedir\\%f"'  # Windows
      </varlistentry>
 
      <varlistentry id="guc-constraint-exclusion" xreflabel="constraint_exclusion">
-      <term><varname>constraint_exclusion</varname> (<type>boolean</type>)</term>
+      <term><varname>constraint_exclusion</varname> (<type>enum</type>)</term>
       <indexterm>
        <primary>constraint exclusion</primary>
       </indexterm>
@@ -2155,14 +2155,20 @@ archive_command = 'copy "%p" "C:\\server\\archivedir\\%f"'  # Windows
       <listitem>
        <para>
         Enables or disables the query planner's use of table constraints to
-        optimize queries.  The default is <literal>off</>.
+        optimize queries.
+        The allowed values of <varname>constraint_exclusion</> are
+        <literal>on</> (examine constraints for all tables),
+        <literal>off</> (never examine constraints), and
+        <literal>partition</> (examine constraints only for inheritance child
+        tables and <literal>UNION ALL</> subqueries).
+        <literal>partition</> is the default setting.
        </para>
 
        <para>
-        When this parameter is <literal>on</>, the planner compares
-        query conditions with table <literal>CHECK</> constraints, and
-        omits scanning tables for which the conditions contradict the
-        constraints.  For example:
+        When this parameter allows it for a particular table, the planner
+        compares query conditions with the table's <literal>CHECK</>
+        constraints, and omits scanning tables for which the conditions
+        contradict the constraints.  For example:
 
 <programlisting>
 CREATE TABLE parent(key integer, ...);
@@ -2179,17 +2185,17 @@ SELECT * FROM parent WHERE key = 2400;
        </para>
 
        <para>
-        Currently, <varname>constraint_exclusion</> is disabled by
-        default because the constraint checks are relatively
-        expensive, and in many circumstances will yield no savings.
-        It is recommended to turn this on only if you are actually
-        using partitioned tables designed to take advantage of the
-        feature.
+        Currently, constraint exclusion is enabled by default
+        only for cases that are often used to implement table partitioning.
+        Turning it on for all tables imposes extra planning overhead that is
+        quite noticeable on simple queries, and most often will yield no
+        benefit for simple queries.  If you have no partitioned tables
+        you might prefer to turn it off entirely.
        </para>
 
        <para>
-        Refer to <xref linkend="ddl-partitioning"> for more information
-        on using constraint exclusion and partitioning.
+        Refer to <xref linkend="ddl-partitioning-constraint-exclusion"> for
+        more information on using constraint exclusion and partitioning.
        </para>
       </listitem>
      </varlistentry>
index 94341df0f4b433796fa9aa13ead65d2e40306acf..6c89170b34930a92d91c5c51d46ddd20900fedde 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/ddl.sgml,v 1.83 2008/09/08 00:47:40 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/ddl.sgml,v 1.84 2009/01/07 22:40:49 tgl Exp $ -->
 
 <chapter id="ddl">
  <title>Data Definition</title>
@@ -2135,7 +2135,7 @@ VALUES ('New York', NULL, NULL, 'NY');
    an existing inheritance hierarchy, be careful to grant all the needed
    permissions on it.
   </para>
+
   <para>
    A serious limitation of the inheritance feature is that indexes (including
    unique constraints) and foreign key constraints only apply to single
@@ -2394,9 +2394,9 @@ CHECK ( outletID BETWEEN 200 AND 300 )
       <listitem>
        <para>
         Ensure that the <xref linkend="guc-constraint-exclusion">
-        configuration
-        parameter is enabled in <filename>postgresql.conf</>.  Without
-        this, queries will not be optimized as desired.
+        configuration parameter is not disabled in
+        <filename>postgresql.conf</>.
+        If it is, queries will not be optimized as desired.
        </para>
       </listitem>
 
@@ -2698,7 +2698,7 @@ SELECT count(*) FROM measurement WHERE logdate &gt;= DATE '2008-01-01';
    <para>
     You can use the <command>EXPLAIN</> command to show the difference
     between a plan with <varname>constraint_exclusion</> on and a plan
-    with it off.  A typical default plan for this type of table setup is:
+    with it off.  A typical unoptimized plan for this type of table setup is:
 
 <programlisting>
 SET constraint_exclusion = off;
@@ -2725,7 +2725,7 @@ EXPLAIN SELECT count(*) FROM measurement WHERE logdate &gt;= DATE '2008-01-01';
     full-table sequential scans, but the point here is that there
     is no need to scan the older partitions at all to answer this query.
     When we enable constraint exclusion, we get a significantly
-    reduced plan that will deliver the same answer:
+    cheaper plan that will deliver the same answer:
 
 <programlisting>
 SET constraint_exclusion = on;
@@ -2751,6 +2751,17 @@ EXPLAIN SELECT count(*) FROM measurement WHERE logdate &gt;= DATE '2008-01-01';
     be helpful in the latter case but not the former.
    </para>
 
+   <para>
+    The default (and recommended) setting of
+    <xref linkend="guc-constraint-exclusion"> is actually neither
+    <literal>on</> nor <literal>off</>, but an intermediate setting
+    called <literal>partition</>, which causes the technique to be
+    applied only to queries that are likely to be working on partitioned
+    tables.  The <literal>on</> setting causes the planner to examine
+    <literal>CHECK</> constraints in all queries, even simple ones that
+    are unlikely to benefit.
+   </para>
+
    </sect2>
 
    <sect2 id="ddl-partitioning-alternatives">
@@ -2817,7 +2828,7 @@ UNION ALL SELECT * FROM measurement_y2008m01;
 
    <sect2 id="ddl-partitioning-caveats">
    <title>Caveats</title>
+
    <para>
     The following caveats apply to partitioned tables:
    <itemizedlist>
index ac8b75512e071845ff8cca0329d594435c419a9b..4b18b06c528d69a687a358dbbb5541d015dc97a4 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/textsearch.sgml,v 1.46 2008/10/17 18:05:19 teodor Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/textsearch.sgml,v 1.47 2009/01/07 22:40:49 tgl Exp $ -->
 
 <chapter id="textsearch">
  <title id="textsearch-title">Full Text Search</title>
@@ -3254,8 +3254,8 @@ SELECT plainto_tsquery('supernovae stars');
   <para>
    Partitioning of big collections and the proper use of GiST and GIN indexes
    allows the implementation of very fast searches with online update.
-   Partitioning can be done at the database level using table inheritance
-   and <varname>constraint_exclusion</>, or by distributing documents over
+   Partitioning can be done at the database level using table inheritance,
+   or by distributing documents over
    servers and collecting search results using the <filename>contrib/dblink</>
    extension module. The latter is possible because ranking functions use
    only local information.
index 948c0602136c1950872041d44ffc4108157b608c..f4f8ac8a763b27886e61aa924f3756b4945fcddf 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.153 2009/01/01 17:23:45 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.154 2009/01/07 22:40:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,6 +27,7 @@
 #include "nodes/makefuncs.h"
 #include "nodes/nodeFuncs.h"
 #include "optimizer/clauses.h"
+#include "optimizer/cost.h"
 #include "optimizer/plancat.h"
 #include "optimizer/predtest.h"
 #include "optimizer/prep.h"
@@ -43,7 +44,7 @@
 
 
 /* GUC parameter */
-bool           constraint_exclusion = false;
+int                    constraint_exclusion = CONSTRAINT_EXCLUSION_PARTITION;
 
 /* Hook for plugins to get control in get_relation_info() */
 get_relation_info_hook_type get_relation_info_hook = NULL;
@@ -561,8 +562,9 @@ get_relation_constraints(PlannerInfo *root,
  * self-inconsistent restrictions, or restrictions inconsistent with the
  * relation's CHECK constraints.
  *
- * Note: this examines only rel->relid and rel->baserestrictinfo; therefore
- * it can be called before filling in other fields of the RelOptInfo.
+ * Note: this examines only rel->relid, rel->reloptkind, and
+ * rel->baserestrictinfo; therefore it can be called before filling in
+ * other fields of the RelOptInfo.
  */
 bool
 relation_excluded_by_constraints(PlannerInfo *root,
@@ -573,8 +575,10 @@ relation_excluded_by_constraints(PlannerInfo *root,
        List       *safe_constraints;
        ListCell   *lc;
 
-       /* Skip the test if constraint exclusion is disabled */
-       if (!constraint_exclusion)
+       /* Skip the test if constraint exclusion is disabled for the rel */
+       if (constraint_exclusion == CONSTRAINT_EXCLUSION_OFF ||
+               (constraint_exclusion == CONSTRAINT_EXCLUSION_PARTITION &&
+                rel->reloptkind != RELOPT_OTHER_MEMBER_REL))
                return false;
 
        /*
index 479279cdc432a122325e79d4dad5af23fd554e78..22cfbff610507d3527958f46320b67051d50957c 100644 (file)
@@ -10,7 +10,7 @@
  * Written by Peter Eisentraut <peter_e@gmx.net>.
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.490 2009/01/06 16:39:52 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.491 2009/01/07 22:40:49 tgl Exp $
  *
  *--------------------------------------------------------------------
  */
@@ -311,6 +311,23 @@ static const struct config_enum_entry backslash_quote_options[] = {
        {NULL, 0, false}
 };
 
+/*
+ * Although only "on", "off", and "partition" are documented, we
+ * accept all the likely variants of "on" and "off".
+ */
+static const struct config_enum_entry constraint_exclusion_options[] = {
+       {"partition", CONSTRAINT_EXCLUSION_PARTITION, false},
+       {"on", CONSTRAINT_EXCLUSION_ON, false},
+       {"off", CONSTRAINT_EXCLUSION_OFF, false},
+       {"true", CONSTRAINT_EXCLUSION_ON, true},
+       {"false", CONSTRAINT_EXCLUSION_OFF, true},
+       {"yes", CONSTRAINT_EXCLUSION_ON, true},
+       {"no", CONSTRAINT_EXCLUSION_OFF, true},
+       {"1", CONSTRAINT_EXCLUSION_ON, true},
+       {"0", CONSTRAINT_EXCLUSION_OFF, true},
+       {NULL, 0, false}
+};
+
 /*
  * Options for enum values stored in other modules
  */
@@ -635,15 +652,6 @@ static struct config_bool ConfigureNamesBool[] =
                &enable_hashjoin,
                true, NULL, NULL
        },
-       {
-               {"constraint_exclusion", PGC_USERSET, QUERY_TUNING_OTHER,
-                       gettext_noop("Enables the planner to use constraints to optimize queries."),
-                       gettext_noop("Child table scans will be skipped if their "
-                                          "constraints guarantee that no rows match the query.")
-               },
-               &constraint_exclusion,
-               false, NULL, NULL
-       },
        {
                {"geqo", PGC_USERSET, QUERY_TUNING_GEQO,
                        gettext_noop("Enables genetic query optimization."),
@@ -2521,6 +2529,17 @@ static struct config_enum ConfigureNamesEnum[] =
                NOTICE, client_message_level_options, NULL, NULL
        },
 
+       {
+               {"constraint_exclusion", PGC_USERSET, QUERY_TUNING_OTHER,
+                       gettext_noop("Enables the planner to use constraints to optimize queries."),
+                       gettext_noop("Table scans will be skipped if their constraints"
+                                                " guarantee that no rows match the query.")
+               },
+               &constraint_exclusion,
+               CONSTRAINT_EXCLUSION_PARTITION, constraint_exclusion_options,
+               NULL, NULL
+       },
+
        {
                {"default_transaction_isolation", PGC_USERSET, CLIENT_CONN_STATEMENT,
                        gettext_noop("Sets the transaction isolation level of each new transaction."),
index e28feb8e4283708aee5fed249cd88a4ce80a40ff..d53861511aea366f3dad3c217e11feb22f26e772 100644 (file)
 # - Other Planner Options -
 
 #default_statistics_target = 100       # range 1-10000
-#constraint_exclusion = off
+#constraint_exclusion = partition      # on, off, or partition
 #cursor_tuple_fraction = 0.1           # range 0.0-1.0
 #from_collapse_limit = 8
 #join_collapse_limit = 8               # 1 disables collapsing of explicit 
index 39ece8f4ff787ac6dda322e32dfa3310ff4e33ad..27600fa1acc96066d8ef06ccefe610cdec92009a 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/cost.h,v 1.95 2009/01/01 17:24:00 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/cost.h,v 1.96 2009/01/07 22:40:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #define DEFAULT_EFFECTIVE_CACHE_SIZE  16384            /* measured in pages */
 
+typedef enum
+{
+       CONSTRAINT_EXCLUSION_OFF,                       /* do not use c_e */
+       CONSTRAINT_EXCLUSION_ON,                        /* apply c_e to all rels */
+       CONSTRAINT_EXCLUSION_PARTITION          /* apply c_e to otherrels only */
+} ConstraintExclusionType;
+
 
 /*
  * prototypes for costsize.c
@@ -52,7 +59,7 @@ extern bool enable_hashagg;
 extern bool enable_nestloop;
 extern bool enable_mergejoin;
 extern bool enable_hashjoin;
-extern bool constraint_exclusion;
+extern int     constraint_exclusion;
 
 extern double clamp_row_est(double nrows);
 extern double index_pages_fetched(double tuples_fetched, BlockNumber pages,