From a43f20cb0a38523dd4dcf6265884e30ba2b1ec22 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Wed, 25 Apr 2001 22:04:37 +0000
Subject: [PATCH] Tweak nestloop costing to weight restart cost of inner path
 more heavily. Without this, it was making some pretty silly decisions about
 whether an expensive sub-SELECT should be the inner or outer side of a
 join...

---
 src/backend/optimizer/path/costsize.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index d5b343a90cf..c52af72a16b 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -41,7 +41,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.69 2001/03/22 03:59:34 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.70 2001/04/25 22:04:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -443,14 +443,22 @@ cost_nestloop(Path *path,
 	/* cost of source data */
 
 	/*
-	 * NOTE: we assume that the inner path's startup_cost is paid once,
-	 * not over again on each restart.	This is certainly correct if the
-	 * inner path is materialized.	Are there any cases where it is wrong?
+	 * NOTE: clearly, we must pay both outer and inner paths' startup_cost
+	 * before we can start returning tuples, so the join's startup cost
+	 * is their sum.  What's not so clear is whether the inner path's
+	 * startup_cost must be paid again on each rescan of the inner path.
+	 * This is not true if the inner path is materialized, but probably
+	 * is true otherwise.  Since we don't yet have clean handling of the
+	 * decision whether to materialize a path, we can't tell here which
+	 * will happen.  As a compromise, charge 50% of the inner startup cost
+	 * for each restart.
 	 */
 	startup_cost += outer_path->startup_cost + inner_path->startup_cost;
 	run_cost += outer_path->total_cost - outer_path->startup_cost;
 	run_cost += outer_path->parent->rows *
 		(inner_path->total_cost - inner_path->startup_cost);
+	if (outer_path->parent->rows > 1)
+		run_cost += (outer_path->parent->rows - 1) * inner_path->startup_cost;
 
 	/*
 	 * Number of tuples processed (not number emitted!).  If inner path is
-- 
GitLab