aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/optimizer/path/costsize.c46
-rw-r--r--src/backend/optimizer/plan/subselect.c9
-rw-r--r--src/include/optimizer/cost.h3
3 files changed, 49 insertions, 9 deletions
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index f76c778998b..d1eb29691a0 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -54,7 +54,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.185 2007/06/11 01:16:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.186 2007/09/22 21:36:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -2049,9 +2049,10 @@ cost_qual_eval_walker(Node *node, cost_qual_eval_context *context)
{
/*
* Otherwise we will be rescanning the subplan output on each
- * evaluation. We need to estimate how much of the output we will
- * actually need to scan. NOTE: this logic should agree with the
- * estimates used by make_subplan() in plan/subselect.c.
+ * evaluation. We need to estimate how much of the output we will
+ * actually need to scan. NOTE: this logic should agree with
+ * get_initplan_cost, below, and with the estimates used by
+ * make_subplan() in plan/subselect.c.
*/
Cost plan_run_cost = plan->total_cost - plan->startup_cost;
@@ -2098,6 +2099,43 @@ cost_qual_eval_walker(Node *node, cost_qual_eval_context *context)
/*
+ * get_initplan_cost
+ * Get the expected cost of evaluating an initPlan.
+ *
+ * Keep this in sync with cost_qual_eval_walker's handling of subplans, above,
+ * and with the estimates used by make_subplan() in plan/subselect.c.
+ */
+Cost
+get_initplan_cost(PlannerInfo *root, SubPlan *subplan)
+{
+ Cost result;
+ Plan *plan = planner_subplan_get_plan(root, subplan);
+
+ /* initPlans never use hashtables */
+ Assert(!subplan->useHashTable);
+ /* they are never ALL or ANY, either */
+ Assert(!(subplan->subLinkType == ALL_SUBLINK ||
+ subplan->subLinkType == ANY_SUBLINK));
+
+ if (subplan->subLinkType == EXISTS_SUBLINK)
+ {
+ /* we only need to fetch 1 tuple */
+ Cost plan_run_cost = plan->total_cost - plan->startup_cost;
+
+ result = plan->startup_cost;
+ result += plan_run_cost / plan->plan_rows;
+ }
+ else
+ {
+ /* assume we need all tuples */
+ result = plan->total_cost;
+ }
+
+ return result;
+}
+
+
+/*
* approx_selectivity
* Quick-and-dirty estimation of clause selectivities.
* The input can be either an implicitly-ANDed list of boolean
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index 8b739e16d44..76d80bfce0f 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.124 2007/08/26 21:44:25 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.125 2007/09/22 21:36:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -18,6 +18,7 @@
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "optimizer/clauses.h"
+#include "optimizer/cost.h"
#include "optimizer/planmain.h"
#include "optimizer/planner.h"
#include "optimizer/subselect.h"
@@ -266,7 +267,7 @@ make_subplan(PlannerInfo *root, SubLink *slink, Node *testexpr, bool isTopQual)
* (we're only expecting one row out, anyway).
*
* NOTE: if you change these numbers, also change cost_qual_eval_walker()
- * in path/costsize.c.
+ * and get_initplan_cost() in path/costsize.c.
*
* XXX If an ALL/ANY subplan is uncorrelated, we may decide to hash or
* materialize its result below. In that case it would've been better to
@@ -1021,7 +1022,7 @@ SS_finalize_plan(PlannerInfo *root, Plan *plan)
* have extParams that are setParams of other initPlans, so we have to
* take care of this situation explicitly.)
*
- * We also add the total_cost of each initPlan to the startup cost of the
+ * We also add the eval cost of each initPlan to the startup cost of the
* top node. This is a conservative overestimate, since in fact each
* initPlan might be executed later than plan startup, or even not at all.
*/
@@ -1041,7 +1042,7 @@ SS_finalize_plan(PlannerInfo *root, Plan *plan)
{
initSetParam = bms_add_member(initSetParam, lfirst_int(l2));
}
- initplan_cost += initplan->total_cost;
+ initplan_cost += get_initplan_cost(root, initsubplan);
}
/* allParam must include all these params */
plan->allParam = bms_add_members(plan->allParam, initExtParam);
diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h
index dc052dcf55f..22034850148 100644
--- a/src/include/optimizer/cost.h
+++ b/src/include/optimizer/cost.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/optimizer/cost.h,v 1.88 2007/07/25 12:22:53 mha Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/cost.h,v 1.89 2007/09/22 21:36:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -92,6 +92,7 @@ extern void cost_mergejoin(MergePath *path, PlannerInfo *root);
extern void cost_hashjoin(HashPath *path, PlannerInfo *root);
extern void cost_qual_eval(QualCost *cost, List *quals, PlannerInfo *root);
extern void cost_qual_eval_node(QualCost *cost, Node *qual, PlannerInfo *root);
+extern Cost get_initplan_cost(PlannerInfo *root, SubPlan *subplan);
extern void set_baserel_size_estimates(PlannerInfo *root, RelOptInfo *rel);
extern void set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel,
RelOptInfo *outer_rel,