aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/pathnode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/util/pathnode.c')
-rw-r--r--src/backend/optimizer/util/pathnode.c42
1 files changed, 33 insertions, 9 deletions
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index 5996af2b5d5..8e32895fb27 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.146 2008/08/14 18:47:59 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.147 2008/09/05 21:07:29 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1304,19 +1304,43 @@ create_mergejoin_path(PlannerInfo *root,
/*
* If we are not sorting the inner path, we may need a materialize node to
- * ensure it can be marked/restored. (Sort does support mark/restore, so
- * no materialize is needed in that case.)
+ * ensure it can be marked/restored.
*
* Since the inner side must be ordered, and only Sorts and IndexScans can
- * create order to begin with, you might think there's no problem --- but
- * you'd be wrong. Nestloop and 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.
+ * create order to begin with, and they both support mark/restore, you
+ * might think there's no problem --- but you'd be wrong. Nestloop and
+ * 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.
+ *
+ * Note: Sort supports mark/restore, so no materialize is really needed
+ * in that case; but one may be desirable anyway to optimize the sort.
+ * However, since we aren't representing the sort step separately in
+ * the Path tree, we can't explicitly represent the materialize either.
+ * So that case is not handled here. Instead, cost_mergejoin has to
+ * factor in the cost and create_mergejoin_plan has to add the plan node.
*/
if (innersortkeys == NIL &&
!ExecSupportsMarkRestore(inner_path->pathtype))
- inner_path = (Path *)
- create_material_path(inner_path->parent, inner_path);
+ {
+ Path *mpath;
+
+ mpath = (Path *) create_material_path(inner_path->parent, inner_path);
+
+ /*
+ * We expect the materialize won't spill to disk (it could only do
+ * so if there were a whole lot of duplicate tuples, which is a case
+ * cost_mergejoin will avoid choosing anyway). Therefore
+ * cost_material's cost estimate is bogus and we should charge
+ * just cpu_tuple_cost per tuple. (Keep this estimate in sync with
+ * similar ones in cost_mergejoin and create_mergejoin_plan.)
+ */
+ mpath->startup_cost = inner_path->startup_cost;
+ mpath->total_cost = inner_path->total_cost;
+ mpath->total_cost += cpu_tuple_cost * inner_path->parent->rows;
+
+ inner_path = mpath;
+ }
pathnode->jpath.path.pathtype = T_MergeJoin;
pathnode->jpath.path.parent = joinrel;