Add an 'enable_material' GUC.
authorRobert Haas <rhaas@postgresql.org>
Mon, 19 Apr 2010 00:55:26 +0000 (00:55 +0000)
committerRobert Haas <rhaas@postgresql.org>
Mon, 19 Apr 2010 00:55:26 +0000 (00:55 +0000)
The logic for determining whether to materialize has been significantly
overhauled for 9.0.  In case there should be any doubt about whether
materialization is a win in any particular case, this should provide a
convenient way of seeing what happens without it; but even with enable_material
turned off, we still materialize in cases where it is required for
correctness.

Thanks to Tom Lane for the review.

doc/src/sgml/config.sgml
src/backend/optimizer/path/costsize.c
src/backend/optimizer/path/joinpath.c
src/backend/optimizer/plan/subselect.c
src/backend/utils/misc/guc.c
src/backend/utils/misc/postgresql.conf.sample
src/include/optimizer/cost.h
src/test/regress/expected/rangefuncs.out

index 986fb1aca45eb34fa6728a254c572dc09dcaefee..eb3e8edd436c3c3e085d3d425eb19b2a093ae4c5 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.267 2010/04/16 21:46:07 rhaas Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.268 2010/04/19 00:55:25 rhaas Exp $ -->
 
 <chapter Id="runtime-config">
   <title>Server Configuration</title>
@@ -2020,6 +2020,22 @@ SET ENABLE_SEQSCAN TO OFF;
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-enable-material" xreflabel="enable_material">
+      <term><varname>enable_material</varname> (<type>boolean</type>)</term>
+      <indexterm>
+       <primary><varname>enable_material</> configuration parameter</primary>
+      </indexterm>
+      <listitem>
+       <para>
+        Enables or disables the query planner's use of materialization.
+        It is impossible to suppress materialization entirely,
+        but turning this variable off prevents the planner from inserting
+        materialize nodes except in cases where it is required for correctness.
+        The default is <literal>on</>.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry id="guc-enable-mergejoin" xreflabel="enable_mergejoin">
       <term><varname>enable_mergejoin</varname> (<type>boolean</type>)</term>
       <indexterm>
index 355db7f6844da846564c16ca4ca586691021f645..1f8dfa854784d30ebedd1536a9c04565949625fa 100644 (file)
@@ -59,7 +59,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.216 2010/02/26 02:00:44 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.217 2010/04/19 00:55:25 rhaas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -114,6 +114,7 @@ bool        enable_tidscan = true;
 bool       enable_sort = true;
 bool       enable_hashagg = true;
 bool       enable_nestloop = true;
+bool       enable_material = true;
 bool       enable_mergejoin = true;
 bool       enable_hashjoin = true;
 
@@ -1852,8 +1853,11 @@ cost_mergejoin(MergePath *path, PlannerInfo *root, SpecialJoinInfo *sjinfo)
    mat_inner_cost = inner_run_cost +
        cpu_operator_cost * inner_path_rows * rescanratio;
 
-   /* Prefer materializing if it looks cheaper */
-   if (mat_inner_cost < bare_inner_cost)
+   /*
+    * Prefer materializing if it looks cheaper, unless the user has asked
+    * to suppress materialization.
+    */
+   if (enable_material && mat_inner_cost < bare_inner_cost)
        path->materialize_inner = true;
 
    /*
@@ -1867,6 +1871,10 @@ cost_mergejoin(MergePath *path, PlannerInfo *root, SpecialJoinInfo *sjinfo)
     * merge joins can *preserve* the order of their inputs, so they can be
     * selected as the input of a mergejoin, and they don't support
     * mark/restore at present.
+    *
+    * We don't test the value of enable_material here, because materialization
+    * is required for correctness in this case, and turning it off does not
+    * entitle us to deliver an invalid plan.
     */
    else if (innersortkeys == NIL &&
             !ExecSupportsMarkRestore(inner_path->pathtype))
@@ -1878,8 +1886,11 @@ cost_mergejoin(MergePath *path, PlannerInfo *root, SpecialJoinInfo *sjinfo)
     * pass can be done on-the-fly if it doesn't have to support mark/restore.
     * We don't try to adjust the cost estimates for this consideration,
     * though.
+    *
+    * Since materialization is a performance optimization in this case, rather
+    * than necessary for correctness, we skip it if enable_material is off.
     */
-   else if (innersortkeys != NIL &&
+   else if (enable_material && innersortkeys != NIL &&
             relation_byte_size(inner_path_rows, inner_path->parent->width) >
             (work_mem * 1024L))
        path->materialize_inner = true;
index 3247c73c01747f7ff46da2a80782b73f9a44755e..1fbb2a4fe928a6dc6da13183f504f81d0ffccd9e 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.132 2010/03/28 22:59:32 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.133 2010/04/19 00:55:25 rhaas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -437,10 +437,12 @@ match_unsorted_outer(PlannerInfo *root,
    else if (nestjoinOK)
    {
        /*
-        * Consider materializing the cheapest inner path, unless it is one
-        * that materializes its output anyway.
+        * Consider materializing the cheapest inner path, unless
+        * enable_material is off or the path in question materializes its
+        * output anyway.
         */
-       if (!ExecMaterializesOutput(inner_cheapest_total->pathtype))
+       if (enable_material &&
+           !ExecMaterializesOutput(inner_cheapest_total->pathtype))
            matpath = (Path *)
                create_material_path(innerrel, inner_cheapest_total);
 
index 16dbc3ad44381a98f35c5cc412244cf59356e277..cf503d51135d2b34947cf3eca30b8cb75be96859 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.161 2010/02/26 02:00:46 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.162 2010/04/19 00:55:25 rhaas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -578,9 +578,11 @@ build_subplan(PlannerInfo *root, Plan *plan, List *rtable, List *rowmarks,
         * is pointless for a direct-correlated subplan, since we'd have to
         * recompute its results each time anyway.  For uncorrelated/undirect
         * correlated subplans, we add Material unless the subplan's top plan
-        * node would materialize its output anyway.
+        * node would materialize its output anyway.  Also, if enable_material
+        * is false, then the user does not want us to materialize anything
+        * unnecessarily, so we don't.
         */
-       else if (splan->parParam == NIL &&
+       else if (splan->parParam == NIL && enable_material &&
                 !ExecMaterializesOutput(nodeTag(plan)))
            plan = materialize_finished_plan(plan);
 
index 9d72a0e57363853bb8a7dc5dbfc5a63f2cb532b3..04ee99ac30a40a4bfb45ef92e6b0d5c5db75c7eb 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.547 2010/04/12 09:52:29 heikki Exp $
+ *   $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.548 2010/04/19 00:55:25 rhaas Exp $
  *
  *--------------------------------------------------------------------
  */
@@ -643,6 +643,14 @@ static struct config_bool ConfigureNamesBool[] =
        &enable_hashagg,
        true, NULL, NULL
    },
+   {
+       {"enable_material", PGC_USERSET, QUERY_TUNING_METHOD,
+           gettext_noop("Enables the planner's use of materialization."),
+           NULL
+       },
+       &enable_material,
+       true, NULL, NULL
+   },
    {
        {"enable_nestloop", PGC_USERSET, QUERY_TUNING_METHOD,
            gettext_noop("Enables the planner's use of nested-loop join plans."),
index 48c09d14670c826453fa9d497a2256705f1ea921..c3f985a2d37540663441ee7d3e8849d50f7776cd 100644 (file)
 #enable_hashagg = on
 #enable_hashjoin = on
 #enable_indexscan = on
+#enable_material = on
 #enable_mergejoin = on
 #enable_nestloop = on
 #enable_seqscan = on
index 940b594d0645a8f1bb6bf3bf5f5b7c76f6d5fe40..ce9f3f5095929c6f03b2138e3f80c9ad6bfdbabe 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/cost.h,v 1.100 2010/01/02 16:58:07 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/cost.h,v 1.101 2010/04/19 00:55:26 rhaas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -57,6 +57,7 @@ extern bool enable_tidscan;
 extern bool enable_sort;
 extern bool enable_hashagg;
 extern bool enable_nestloop;
+extern bool enable_material;
 extern bool enable_mergejoin;
 extern bool enable_hashjoin;
 extern int constraint_exclusion;
index a32cbf5f79587eda538f89d0a746a62495d2509d..66736a3564c41e6c74f120f54a21634c953ca994 100644 (file)
@@ -5,12 +5,13 @@ SELECT name, setting FROM pg_settings WHERE name LIKE 'enable%';
  enable_hashagg    | on
  enable_hashjoin   | on
  enable_indexscan  | on
+ enable_material   | on
  enable_mergejoin  | on
  enable_nestloop   | on
  enable_seqscan    | on
  enable_sort       | on
  enable_tidscan    | on
-(9 rows)
+(10 rows)
 
 CREATE TABLE foo2(fooid int, f2 int);
 INSERT INTO foo2 VALUES(1, 11);