Commit 3d09f6c5 authored by Tom Lane's avatar Tom Lane

Make cost estimates for SubqueryScan more realistic: charge cpu_tuple_cost

for each row processed, and don't forget the evaluation cost of any
restriction clauses attached to the node.  Per discussion with Greg Stark.
parent b8001962
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.109 2003/06/29 23:05:04 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.110 2003/07/14 22:35:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -415,6 +415,38 @@ cost_tidscan(Path *path, Query *root, ...@@ -415,6 +415,38 @@ cost_tidscan(Path *path, Query *root,
path->total_cost = startup_cost + run_cost; path->total_cost = startup_cost + run_cost;
} }
/*
* cost_subqueryscan
* Determines and returns the cost of scanning a subquery RTE.
*/
void
cost_subqueryscan(Path *path, RelOptInfo *baserel)
{
Cost startup_cost;
Cost run_cost;
Cost cpu_per_tuple;
/* Should only be applied to base relations that are subqueries */
Assert(baserel->relid > 0);
Assert(baserel->rtekind == RTE_SUBQUERY);
/*
* Cost of path is cost of evaluating the subplan, plus cost of
* evaluating any restriction clauses that will be attached to the
* SubqueryScan node, plus cpu_tuple_cost to account for selection
* and projection overhead.
*/
path->startup_cost = baserel->subplan->startup_cost;
path->total_cost = baserel->subplan->total_cost;
startup_cost = baserel->baserestrictcost.startup;
cpu_per_tuple = cpu_tuple_cost + baserel->baserestrictcost.per_tuple;
run_cost = cpu_per_tuple * baserel->tuples;
path->startup_cost += startup_cost;
path->total_cost += startup_cost + run_cost;
}
/* /*
* cost_functionscan * cost_functionscan
* Determines and returns the cost of scanning a function RTE. * Determines and returns the cost of scanning a function RTE.
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.147 2003/06/29 23:05:04 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.148 2003/07/14 22:35:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -811,6 +811,8 @@ create_subqueryscan_plan(Path *best_path, List *tlist, List *scan_clauses) ...@@ -811,6 +811,8 @@ create_subqueryscan_plan(Path *best_path, List *tlist, List *scan_clauses)
scan_relid, scan_relid,
best_path->parent->subplan); best_path->parent->subplan);
copy_path_costsize(&scan_plan->scan.plan, best_path);
return scan_plan; return scan_plan;
} }
...@@ -1503,8 +1505,14 @@ make_subqueryscan(List *qptlist, ...@@ -1503,8 +1505,14 @@ make_subqueryscan(List *qptlist,
SubqueryScan *node = makeNode(SubqueryScan); SubqueryScan *node = makeNode(SubqueryScan);
Plan *plan = &node->scan.plan; Plan *plan = &node->scan.plan;
/* cost is figured here for the convenience of prepunion.c */ /*
* Cost is figured here for the convenience of prepunion.c. Note this
* is only correct for the case where qpqual is empty; otherwise caller
* should overwrite cost with a better estimate.
*/
copy_plan_costsize(plan, subplan); copy_plan_costsize(plan, subplan);
plan->total_cost += cpu_tuple_cost * subplan->plan_rows;
plan->targetlist = qptlist; plan->targetlist = qptlist;
plan->qual = qpqual; plan->qual = qpqual;
plan->lefttree = NULL; plan->lefttree = NULL;
...@@ -1540,7 +1548,11 @@ make_append(List *appendplans, bool isTarget, List *tlist) ...@@ -1540,7 +1548,11 @@ make_append(List *appendplans, bool isTarget, List *tlist)
Plan *plan = &node->plan; Plan *plan = &node->plan;
List *subnode; List *subnode;
/* compute costs from subplan costs */ /*
* Compute cost as sum of subplan costs. We charge nothing extra for
* the Append itself, which perhaps is too optimistic, but since it
* doesn't do any selection or projection, it is a pretty cheap node.
*/
plan->startup_cost = 0; plan->startup_cost = 0;
plan->total_cost = 0; plan->total_cost = 0;
plan->plan_rows = 0; plan->plan_rows = 0;
...@@ -1556,6 +1568,7 @@ make_append(List *appendplans, bool isTarget, List *tlist) ...@@ -1556,6 +1568,7 @@ make_append(List *appendplans, bool isTarget, List *tlist)
if (plan->plan_width < subplan->plan_width) if (plan->plan_width < subplan->plan_width)
plan->plan_width = subplan->plan_width; plan->plan_width = subplan->plan_width;
} }
plan->targetlist = tlist; plan->targetlist = tlist;
plan->qual = NIL; plan->qual = NIL;
plan->lefttree = NULL; plan->lefttree = NULL;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.91 2003/06/29 23:05:04 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.92 2003/07/14 22:35:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -686,9 +686,7 @@ create_subqueryscan_path(RelOptInfo *rel, List *pathkeys) ...@@ -686,9 +686,7 @@ create_subqueryscan_path(RelOptInfo *rel, List *pathkeys)
pathnode->parent = rel; pathnode->parent = rel;
pathnode->pathkeys = pathkeys; pathnode->pathkeys = pathkeys;
/* just copy the subplan's cost estimates */ cost_subqueryscan(pathnode, rel);
pathnode->startup_cost = rel->subplan->startup_cost;
pathnode->total_cost = rel->subplan->total_cost;
return pathnode; return pathnode;
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: cost.h,v 1.53 2003/06/11 15:01:15 momjian Exp $ * $Id: cost.h,v 1.54 2003/07/14 22:35:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -56,6 +56,7 @@ extern void cost_index(Path *path, Query *root, ...@@ -56,6 +56,7 @@ extern void cost_index(Path *path, Query *root,
List *indexQuals, bool is_injoin); List *indexQuals, bool is_injoin);
extern void cost_tidscan(Path *path, Query *root, extern void cost_tidscan(Path *path, Query *root,
RelOptInfo *baserel, List *tideval); RelOptInfo *baserel, List *tideval);
extern void cost_subqueryscan(Path *path, RelOptInfo *baserel);
extern void cost_functionscan(Path *path, Query *root, extern void cost_functionscan(Path *path, Query *root,
RelOptInfo *baserel); RelOptInfo *baserel);
extern void cost_sort(Path *path, Query *root, extern void cost_sort(Path *path, Query *root,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment