diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 986fb1aca45eb34fa6728a254c572dc09dcaefee..eb3e8edd436c3c3e085d3d425eb19b2a093ae4c5 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -1,4 +1,4 @@ - + Server Configuration @@ -2020,6 +2020,22 @@ SET ENABLE_SEQSCAN TO OFF; + + enable_material (boolean) + + enable_material configuration parameter + + + + 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 on. + + + + enable_mergejoin (boolean) diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 355db7f6844da846564c16ca4ca586691021f645..1f8dfa854784d30ebedd1536a9c04565949625fa 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -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; diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c index 3247c73c01747f7ff46da2a80782b73f9a44755e..1fbb2a4fe928a6dc6da13183f504f81d0ffccd9e 100644 --- a/src/backend/optimizer/path/joinpath.c +++ b/src/backend/optimizer/path/joinpath.c @@ -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); diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 16dbc3ad44381a98f35c5cc412244cf59356e277..cf503d51135d2b34947cf3eca30b8cb75be96859 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -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); diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 9d72a0e57363853bb8a7dc5dbfc5a63f2cb532b3..04ee99ac30a40a4bfb45ef92e6b0d5c5db75c7eb 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut . * * 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."), diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index 48c09d14670c826453fa9d497a2256705f1ea921..c3f985a2d37540663441ee7d3e8849d50f7776cd 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -206,6 +206,7 @@ #enable_hashagg = on #enable_hashjoin = on #enable_indexscan = on +#enable_material = on #enable_mergejoin = on #enable_nestloop = on #enable_seqscan = on diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h index 940b594d0645a8f1bb6bf3bf5f5b7c76f6d5fe40..ce9f3f5095929c6f03b2138e3f80c9ad6bfdbabe 100644 --- a/src/include/optimizer/cost.h +++ b/src/include/optimizer/cost.h @@ -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; diff --git a/src/test/regress/expected/rangefuncs.out b/src/test/regress/expected/rangefuncs.out index a32cbf5f79587eda538f89d0a746a62495d2509d..66736a3564c41e6c74f120f54a21634c953ca994 100644 --- a/src/test/regress/expected/rangefuncs.out +++ b/src/test/regress/expected/rangefuncs.out @@ -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);