Skip to content

Commit 3d09f6c

Browse files
committed
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.
1 parent b800196 commit 3d09f6c

File tree

4 files changed

+53
-9
lines changed

4 files changed

+53
-9
lines changed

src/backend/optimizer/path/costsize.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
* Portions Copyright (c) 1994, Regents of the University of California
5050
*
5151
* IDENTIFICATION
52-
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.109 2003/06/29 23:05:04 tgl Exp $
52+
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.110 2003/07/14 22:35:54 tgl Exp $
5353
*
5454
*-------------------------------------------------------------------------
5555
*/
@@ -415,6 +415,38 @@ cost_tidscan(Path *path, Query *root,
415415
path->total_cost = startup_cost + run_cost;
416416
}
417417

418+
/*
419+
* cost_subqueryscan
420+
* Determines and returns the cost of scanning a subquery RTE.
421+
*/
422+
void
423+
cost_subqueryscan(Path *path, RelOptInfo *baserel)
424+
{
425+
Cost startup_cost;
426+
Cost run_cost;
427+
Cost cpu_per_tuple;
428+
429+
/* Should only be applied to base relations that are subqueries */
430+
Assert(baserel->relid > 0);
431+
Assert(baserel->rtekind == RTE_SUBQUERY);
432+
433+
/*
434+
* Cost of path is cost of evaluating the subplan, plus cost of
435+
* evaluating any restriction clauses that will be attached to the
436+
* SubqueryScan node, plus cpu_tuple_cost to account for selection
437+
* and projection overhead.
438+
*/
439+
path->startup_cost = baserel->subplan->startup_cost;
440+
path->total_cost = baserel->subplan->total_cost;
441+
442+
startup_cost = baserel->baserestrictcost.startup;
443+
cpu_per_tuple = cpu_tuple_cost + baserel->baserestrictcost.per_tuple;
444+
run_cost = cpu_per_tuple * baserel->tuples;
445+
446+
path->startup_cost += startup_cost;
447+
path->total_cost += startup_cost + run_cost;
448+
}
449+
418450
/*
419451
* cost_functionscan
420452
* Determines and returns the cost of scanning a function RTE.

src/backend/optimizer/plan/createplan.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
*
1212
* IDENTIFICATION
13-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.147 2003/06/29 23:05:04 tgl Exp $
13+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.148 2003/07/14 22:35:54 tgl Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -811,6 +811,8 @@ create_subqueryscan_plan(Path *best_path, List *tlist, List *scan_clauses)
811811
scan_relid,
812812
best_path->parent->subplan);
813813

814+
copy_path_costsize(&scan_plan->scan.plan, best_path);
815+
814816
return scan_plan;
815817
}
816818

@@ -1503,8 +1505,14 @@ make_subqueryscan(List *qptlist,
15031505
SubqueryScan *node = makeNode(SubqueryScan);
15041506
Plan *plan = &node->scan.plan;
15051507

1506-
/* cost is figured here for the convenience of prepunion.c */
1508+
/*
1509+
* Cost is figured here for the convenience of prepunion.c. Note this
1510+
* is only correct for the case where qpqual is empty; otherwise caller
1511+
* should overwrite cost with a better estimate.
1512+
*/
15071513
copy_plan_costsize(plan, subplan);
1514+
plan->total_cost += cpu_tuple_cost * subplan->plan_rows;
1515+
15081516
plan->targetlist = qptlist;
15091517
plan->qual = qpqual;
15101518
plan->lefttree = NULL;
@@ -1540,7 +1548,11 @@ make_append(List *appendplans, bool isTarget, List *tlist)
15401548
Plan *plan = &node->plan;
15411549
List *subnode;
15421550

1543-
/* compute costs from subplan costs */
1551+
/*
1552+
* Compute cost as sum of subplan costs. We charge nothing extra for
1553+
* the Append itself, which perhaps is too optimistic, but since it
1554+
* doesn't do any selection or projection, it is a pretty cheap node.
1555+
*/
15441556
plan->startup_cost = 0;
15451557
plan->total_cost = 0;
15461558
plan->plan_rows = 0;
@@ -1556,6 +1568,7 @@ make_append(List *appendplans, bool isTarget, List *tlist)
15561568
if (plan->plan_width < subplan->plan_width)
15571569
plan->plan_width = subplan->plan_width;
15581570
}
1571+
15591572
plan->targetlist = tlist;
15601573
plan->qual = NIL;
15611574
plan->lefttree = NULL;

src/backend/optimizer/util/pathnode.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.91 2003/06/29 23:05:04 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.92 2003/07/14 22:35:54 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -686,9 +686,7 @@ create_subqueryscan_path(RelOptInfo *rel, List *pathkeys)
686686
pathnode->parent = rel;
687687
pathnode->pathkeys = pathkeys;
688688

689-
/* just copy the subplan's cost estimates */
690-
pathnode->startup_cost = rel->subplan->startup_cost;
691-
pathnode->total_cost = rel->subplan->total_cost;
689+
cost_subqueryscan(pathnode, rel);
692690

693691
return pathnode;
694692
}

src/include/optimizer/cost.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: cost.h,v 1.53 2003/06/11 15:01:15 momjian Exp $
10+
* $Id: cost.h,v 1.54 2003/07/14 22:35:54 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -56,6 +56,7 @@ extern void cost_index(Path *path, Query *root,
5656
List *indexQuals, bool is_injoin);
5757
extern void cost_tidscan(Path *path, Query *root,
5858
RelOptInfo *baserel, List *tideval);
59+
extern void cost_subqueryscan(Path *path, RelOptInfo *baserel);
5960
extern void cost_functionscan(Path *path, Query *root,
6061
RelOptInfo *baserel);
6162
extern void cost_sort(Path *path, Query *root,

0 commit comments

Comments
 (0)