mirror of
https://github.com/postgres/postgres.git
synced 2025-05-01 01:04:50 +03:00
Cause planner to account for evaluation costs in targetlists and
HAVING quals. Normally this is an insignificant effect --- but it will not be insignificant when these clauses contain sub-selects. The added costs cannot affect the planning of the query containing them, but they might have an impact when the query is a sub-query of a larger one.
This commit is contained in:
parent
d1686b42ab
commit
8ac6d952cf
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.128 2002/12/12 15:49:32 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.129 2003/01/13 00:29:25 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1366,6 +1366,7 @@ 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 */
|
||||||
copy_plan_costsize(plan, subplan);
|
copy_plan_costsize(plan, subplan);
|
||||||
plan->targetlist = qptlist;
|
plan->targetlist = qptlist;
|
||||||
plan->qual = qpqual;
|
plan->qual = qpqual;
|
||||||
@ -1488,7 +1489,7 @@ make_hash(List *tlist, List *hashkeys, Plan *lefttree)
|
|||||||
*/
|
*/
|
||||||
plan->startup_cost = plan->total_cost;
|
plan->startup_cost = plan->total_cost;
|
||||||
plan->targetlist = tlist;
|
plan->targetlist = tlist;
|
||||||
plan->qual = NULL;
|
plan->qual = NIL;
|
||||||
plan->lefttree = lefttree;
|
plan->lefttree = lefttree;
|
||||||
plan->righttree = NULL;
|
plan->righttree = NULL;
|
||||||
node->hashkeys = hashkeys;
|
node->hashkeys = hashkeys;
|
||||||
@ -1646,6 +1647,7 @@ make_agg(Query *root, List *tlist, List *qual,
|
|||||||
Agg *node = makeNode(Agg);
|
Agg *node = makeNode(Agg);
|
||||||
Plan *plan = &node->plan;
|
Plan *plan = &node->plan;
|
||||||
Path agg_path; /* dummy for result of cost_agg */
|
Path agg_path; /* dummy for result of cost_agg */
|
||||||
|
QualCost qual_cost;
|
||||||
|
|
||||||
node->aggstrategy = aggstrategy;
|
node->aggstrategy = aggstrategy;
|
||||||
node->numCols = numGroupCols;
|
node->numCols = numGroupCols;
|
||||||
@ -1671,6 +1673,27 @@ make_agg(Query *root, List *tlist, List *qual,
|
|||||||
else
|
else
|
||||||
plan->plan_rows = numGroups;
|
plan->plan_rows = numGroups;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We also need to account for the cost of evaluation of the qual
|
||||||
|
* (ie, the HAVING clause) and the tlist. Note that cost_qual_eval
|
||||||
|
* doesn't charge anything for Aggref nodes; this is okay since
|
||||||
|
* they are really comparable to Vars.
|
||||||
|
*
|
||||||
|
* See notes in grouping_planner about why this routine and make_group
|
||||||
|
* are the only ones in this file that worry about tlist eval cost.
|
||||||
|
*/
|
||||||
|
if (qual)
|
||||||
|
{
|
||||||
|
cost_qual_eval(&qual_cost, qual);
|
||||||
|
plan->startup_cost += qual_cost.startup;
|
||||||
|
plan->total_cost += qual_cost.startup;
|
||||||
|
plan->total_cost += qual_cost.per_tuple * plan->plan_rows;
|
||||||
|
}
|
||||||
|
cost_qual_eval(&qual_cost, tlist);
|
||||||
|
plan->startup_cost += qual_cost.startup;
|
||||||
|
plan->total_cost += qual_cost.startup;
|
||||||
|
plan->total_cost += qual_cost.per_tuple * plan->plan_rows;
|
||||||
|
|
||||||
plan->qual = qual;
|
plan->qual = qual;
|
||||||
plan->targetlist = tlist;
|
plan->targetlist = tlist;
|
||||||
plan->lefttree = lefttree;
|
plan->lefttree = lefttree;
|
||||||
@ -1690,6 +1713,7 @@ make_group(Query *root,
|
|||||||
Group *node = makeNode(Group);
|
Group *node = makeNode(Group);
|
||||||
Plan *plan = &node->plan;
|
Plan *plan = &node->plan;
|
||||||
Path group_path; /* dummy for result of cost_group */
|
Path group_path; /* dummy for result of cost_group */
|
||||||
|
QualCost qual_cost;
|
||||||
|
|
||||||
node->numCols = numGroupCols;
|
node->numCols = numGroupCols;
|
||||||
node->grpColIdx = grpColIdx;
|
node->grpColIdx = grpColIdx;
|
||||||
@ -1706,7 +1730,23 @@ make_group(Query *root,
|
|||||||
/* One output tuple per estimated result group */
|
/* One output tuple per estimated result group */
|
||||||
plan->plan_rows = numGroups;
|
plan->plan_rows = numGroups;
|
||||||
|
|
||||||
plan->qual = NULL;
|
/*
|
||||||
|
* We also need to account for the cost of evaluation of the tlist.
|
||||||
|
*
|
||||||
|
* XXX this double-counts the cost of evaluation of any expressions
|
||||||
|
* used for grouping, since in reality those will have been evaluated
|
||||||
|
* at a lower plan level and will only be copied by the Group node.
|
||||||
|
* Worth fixing?
|
||||||
|
*
|
||||||
|
* See notes in grouping_planner about why this routine and make_agg
|
||||||
|
* are the only ones in this file that worry about tlist eval cost.
|
||||||
|
*/
|
||||||
|
cost_qual_eval(&qual_cost, tlist);
|
||||||
|
plan->startup_cost += qual_cost.startup;
|
||||||
|
plan->total_cost += qual_cost.startup;
|
||||||
|
plan->total_cost += qual_cost.per_tuple * plan->plan_rows;
|
||||||
|
|
||||||
|
plan->qual = NIL;
|
||||||
plan->targetlist = tlist;
|
plan->targetlist = tlist;
|
||||||
plan->lefttree = lefttree;
|
plan->lefttree = lefttree;
|
||||||
plan->righttree = (Plan *) NULL;
|
plan->righttree = (Plan *) NULL;
|
||||||
@ -1718,7 +1758,6 @@ make_group(Query *root,
|
|||||||
* distinctList is a list of SortClauses, identifying the targetlist items
|
* distinctList is a list of SortClauses, identifying the targetlist items
|
||||||
* that should be considered by the Unique filter.
|
* that should be considered by the Unique filter.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Unique *
|
Unique *
|
||||||
make_unique(List *tlist, Plan *lefttree, List *distinctList)
|
make_unique(List *tlist, Plan *lefttree, List *distinctList)
|
||||||
{
|
{
|
||||||
@ -1911,6 +1950,16 @@ make_result(List *tlist,
|
|||||||
plan->plan_width = 0; /* XXX try to be smarter? */
|
plan->plan_width = 0; /* XXX try to be smarter? */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (resconstantqual)
|
||||||
|
{
|
||||||
|
QualCost qual_cost;
|
||||||
|
|
||||||
|
cost_qual_eval(&qual_cost, (List *) resconstantqual);
|
||||||
|
/* resconstantqual is evaluated once at startup */
|
||||||
|
plan->startup_cost += qual_cost.startup + qual_cost.per_tuple;
|
||||||
|
plan->total_cost += qual_cost.startup + qual_cost.per_tuple;
|
||||||
|
}
|
||||||
|
|
||||||
plan->targetlist = tlist;
|
plan->targetlist = tlist;
|
||||||
plan->qual = NIL;
|
plan->qual = NIL;
|
||||||
plan->lefttree = subplan;
|
plan->lefttree = subplan;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.136 2002/12/19 23:25:01 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.137 2003/01/13 00:29:25 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -966,6 +966,7 @@ grouping_planner(Query *parse, double tuple_fraction)
|
|||||||
List *sub_tlist;
|
List *sub_tlist;
|
||||||
List *group_pathkeys;
|
List *group_pathkeys;
|
||||||
AttrNumber *groupColIdx = NULL;
|
AttrNumber *groupColIdx = NULL;
|
||||||
|
QualCost tlist_cost;
|
||||||
double sub_tuple_fraction;
|
double sub_tuple_fraction;
|
||||||
Path *cheapest_path;
|
Path *cheapest_path;
|
||||||
Path *sorted_path;
|
Path *sorted_path;
|
||||||
@ -1452,6 +1453,27 @@ grouping_planner(Query *parse, double tuple_fraction)
|
|||||||
*/
|
*/
|
||||||
result_plan->targetlist = sub_tlist;
|
result_plan->targetlist = sub_tlist;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Also, account for the cost of evaluation of the sub_tlist.
|
||||||
|
*
|
||||||
|
* Up to now, we have only been dealing with "flat" tlists, containing
|
||||||
|
* just Vars. So their evaluation cost is zero according to the
|
||||||
|
* model used by cost_qual_eval() (or if you prefer, the cost is
|
||||||
|
* factored into cpu_tuple_cost). Thus we can avoid accounting for
|
||||||
|
* tlist cost throughout query_planner() and subroutines.
|
||||||
|
* But now we've inserted a tlist that might contain actual operators,
|
||||||
|
* sub-selects, etc --- so we'd better account for its cost.
|
||||||
|
*
|
||||||
|
* Below this point, any tlist eval cost for added-on nodes should
|
||||||
|
* be accounted for as we create those nodes. Presently, of the
|
||||||
|
* node types we can add on, only Agg and Group project new tlists
|
||||||
|
* (the rest just copy their input tuples) --- so make_agg() and
|
||||||
|
* make_group() are responsible for computing the added cost.
|
||||||
|
*/
|
||||||
|
cost_qual_eval(&tlist_cost, sub_tlist);
|
||||||
|
result_plan->startup_cost += tlist_cost.startup;
|
||||||
|
result_plan->total_cost += tlist_cost.startup +
|
||||||
|
tlist_cost.per_tuple * result_plan->plan_rows;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Insert AGG or GROUP node if needed, plus an explicit sort step
|
* Insert AGG or GROUP node if needed, plus an explicit sort step
|
||||||
|
@ -7,7 +7,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/plan/subselect.c,v 1.64 2003/01/12 04:03:34 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.65 2003/01/13 00:29:26 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -378,6 +378,8 @@ make_subplan(SubLink *slink, List *lefthand)
|
|||||||
plan->plan_width);
|
plan->plan_width);
|
||||||
matplan->startup_cost = matpath.startup_cost;
|
matplan->startup_cost = matpath.startup_cost;
|
||||||
matplan->total_cost = matpath.total_cost;
|
matplan->total_cost = matpath.total_cost;
|
||||||
|
matplan->plan_rows = plan->plan_rows;
|
||||||
|
matplan->plan_width = plan->plan_width;
|
||||||
/* parameter kluge --- see comments above */
|
/* parameter kluge --- see comments above */
|
||||||
matplan->extParam = listCopy(plan->extParam);
|
matplan->extParam = listCopy(plan->extParam);
|
||||||
matplan->locParam = listCopy(plan->locParam);
|
matplan->locParam = listCopy(plan->locParam);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user