4242 * Portions Copyright (c) 1994, Regents of the University of California
4343 *
4444 * IDENTIFICATION
45- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.98 2002/12/30 15:21:21 tgl Exp $
45+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.99 2003/01/12 22:35:29 tgl Exp $
4646 *
4747 *-------------------------------------------------------------------------
4848 */
@@ -87,7 +87,7 @@ boolenable_hashjoin = true;
8787
8888static Selectivity estimate_hash_bucketsize (Query * root ,Var * var ,
8989int nbuckets );
90- static bool cost_qual_eval_walker (Node * node ,Cost * total );
90+ static bool cost_qual_eval_walker (Node * node ,QualCost * total );
9191static Selectivity approx_selectivity (Query * root ,List * quals );
9292static void set_rel_width (Query * root ,RelOptInfo * rel );
9393static double relation_byte_size (double tuples ,int width );
@@ -131,7 +131,8 @@ cost_seqscan(Path *path, Query *root,
131131run_cost += baserel -> pages ;/* sequential fetches with cost 1.0 */
132132
133133/* CPU costs */
134- cpu_per_tuple = cpu_tuple_cost + baserel -> baserestrictcost ;
134+ startup_cost += baserel -> baserestrictcost .startup ;
135+ cpu_per_tuple = cpu_tuple_cost + baserel -> baserestrictcost .per_tuple ;
135136run_cost += cpu_per_tuple * baserel -> tuples ;
136137
137138path -> startup_cost = startup_cost ;
@@ -344,17 +345,25 @@ cost_index(Path *path, Query *root,
344345 *
345346 * Normally the indexquals will be removed from the list of restriction
346347 * clauses that we have to evaluate as qpquals, so we should subtract
347- * their costs from baserestrictcost. XXX For a lossy index, not all
348- * the quals will be removed and so we really shouldn't subtract their
349- * costs; but detecting that seems more expensive than it's worth.
350- * Also, if we are doing a join then some of the indexquals are join
351- * clauses and shouldn't be subtracted. Rather than work out exactly
352- * how much to subtract, we don't subtract anything.
348+ * their costs from baserestrictcost. But if we are doing a join then
349+ * some of the indexquals are join clauses and shouldn't be subtracted.
350+ * Rather than work out exactly how much to subtract, we don't subtract
351+ * anything.
352+ *
353+ * XXX For a lossy index, not all the quals will be removed and so we
354+ * really shouldn't subtract their costs; but detecting that seems more
355+ * expensive than it's worth.
353356 */
354- cpu_per_tuple = cpu_tuple_cost + baserel -> baserestrictcost ;
357+ startup_cost += baserel -> baserestrictcost .startup ;
358+ cpu_per_tuple = cpu_tuple_cost + baserel -> baserestrictcost .per_tuple ;
355359
356360if (!is_injoin )
357- cpu_per_tuple -= cost_qual_eval (indexQuals );
361+ {
362+ QualCost index_qual_cost ;
363+
364+ cost_qual_eval (& index_qual_cost ,indexQuals );
365+ cpu_per_tuple -= index_qual_cost .per_tuple ;
366+ }
358367
359368run_cost += cpu_per_tuple * tuples_fetched ;
360369
@@ -386,7 +395,8 @@ cost_tidscan(Path *path, Query *root,
386395run_cost += random_page_cost * ntuples ;
387396
388397/* CPU costs */
389- cpu_per_tuple = cpu_tuple_cost + baserel -> baserestrictcost ;
398+ startup_cost += baserel -> baserestrictcost .startup ;
399+ cpu_per_tuple = cpu_tuple_cost + baserel -> baserestrictcost .per_tuple ;
390400run_cost += cpu_per_tuple * ntuples ;
391401
392402path -> startup_cost = startup_cost ;
@@ -416,7 +426,8 @@ cost_functionscan(Path *path, Query *root, RelOptInfo *baserel)
416426cpu_per_tuple = cpu_operator_cost ;
417427
418428/* Add scanning CPU costs */
419- cpu_per_tuple += cpu_tuple_cost + baserel -> baserestrictcost ;
429+ startup_cost += baserel -> baserestrictcost .startup ;
430+ cpu_per_tuple += cpu_tuple_cost + baserel -> baserestrictcost .per_tuple ;
420431run_cost += cpu_per_tuple * baserel -> tuples ;
421432
422433path -> startup_cost = startup_cost ;
@@ -656,6 +667,7 @@ cost_nestloop(Path *path, Query *root,
656667Cost startup_cost = 0 ;
657668Cost run_cost = 0 ;
658669Cost cpu_per_tuple ;
670+ QualCost restrict_qual_cost ;
659671double ntuples ;
660672
661673if (!enable_nestloop )
@@ -703,7 +715,9 @@ cost_nestloop(Path *path, Query *root,
703715ntuples *=outer_path -> parent -> rows ;
704716
705717/* CPU costs */
706- cpu_per_tuple = cpu_tuple_cost + cost_qual_eval (restrictlist );
718+ cost_qual_eval (& restrict_qual_cost ,restrictlist );
719+ startup_cost += restrict_qual_cost .startup ;
720+ cpu_per_tuple = cpu_tuple_cost + restrict_qual_cost .per_tuple ;
707721run_cost += cpu_per_tuple * ntuples ;
708722
709723path -> startup_cost = startup_cost ;
@@ -736,6 +750,7 @@ cost_mergejoin(Path *path, Query *root,
736750Cost startup_cost = 0 ;
737751Cost run_cost = 0 ;
738752Cost cpu_per_tuple ;
753+ QualCost restrict_qual_cost ;
739754RestrictInfo * firstclause ;
740755Var * leftvar ;
741756double outer_rows ,
@@ -850,7 +865,9 @@ cost_mergejoin(Path *path, Query *root,
850865outer_path -> parent -> rows * inner_path -> parent -> rows ;
851866
852867/* CPU costs */
853- cpu_per_tuple = cpu_tuple_cost + cost_qual_eval (restrictlist );
868+ cost_qual_eval (& restrict_qual_cost ,restrictlist );
869+ startup_cost += restrict_qual_cost .startup ;
870+ cpu_per_tuple = cpu_tuple_cost + restrict_qual_cost .per_tuple ;
854871run_cost += cpu_per_tuple * ntuples ;
855872
856873path -> startup_cost = startup_cost ;
@@ -878,6 +895,7 @@ cost_hashjoin(Path *path, Query *root,
878895Cost startup_cost = 0 ;
879896Cost run_cost = 0 ;
880897Cost cpu_per_tuple ;
898+ QualCost restrict_qual_cost ;
881899double ntuples ;
882900double outerbytes = relation_byte_size (outer_path -> parent -> rows ,
883901outer_path -> parent -> width );
@@ -984,7 +1002,9 @@ cost_hashjoin(Path *path, Query *root,
9841002outer_path -> parent -> rows * inner_path -> parent -> rows ;
9851003
9861004/* CPU costs */
987- cpu_per_tuple = cpu_tuple_cost + cost_qual_eval (restrictlist );
1005+ cost_qual_eval (& restrict_qual_cost ,restrictlist );
1006+ startup_cost += restrict_qual_cost .startup ;
1007+ cpu_per_tuple = cpu_tuple_cost + restrict_qual_cost .per_tuple ;
9881008run_cost += cpu_per_tuple * ntuples ;
9891009
9901010/*
@@ -1185,16 +1205,20 @@ estimate_hash_bucketsize(Query *root, Var *var, int nbuckets)
11851205
11861206/*
11871207 * cost_qual_eval
1188- *Estimate the CPUcost of evaluating a WHERE clause (once) .
1208+ *Estimate the CPUcosts of evaluating a WHERE clause.
11891209 *The input can be either an implicitly-ANDed list of boolean
11901210 *expressions, or a list of RestrictInfo nodes.
1211+ *The result includes both a one-time (startup) component,
1212+ *and a per-evaluation component.
11911213 */
1192- Cost
1193- cost_qual_eval (List * quals )
1214+ void
1215+ cost_qual_eval (QualCost * cost , List * quals )
11941216{
1195- Cost total = 0 ;
11961217List * l ;
11971218
1219+ cost -> startup = 0 ;
1220+ cost -> per_tuple = 0 ;
1221+
11981222/* We don't charge any cost for the implicit ANDing at top level ... */
11991223
12001224foreach (l ,quals )
@@ -1205,31 +1229,32 @@ cost_qual_eval(List *quals)
12051229 * RestrictInfo nodes contain an eval_cost field reserved for this
12061230 * routine's use, so that it's not necessary to evaluate the qual
12071231 * clause's cost more than once. If the clause's cost hasn't been
1208- * computed yet, the field will contain -1.
1232+ * computed yet, the field's startup value will contain -1.
12091233 */
12101234if (qual && IsA (qual ,RestrictInfo ))
12111235{
12121236RestrictInfo * restrictinfo = (RestrictInfo * )qual ;
12131237
1214- if (restrictinfo -> eval_cost < 0 )
1238+ if (restrictinfo -> eval_cost . startup < 0 )
12151239{
1216- restrictinfo -> eval_cost = 0 ;
1240+ restrictinfo -> eval_cost .startup = 0 ;
1241+ restrictinfo -> eval_cost .per_tuple = 0 ;
12171242cost_qual_eval_walker ((Node * )restrictinfo -> clause ,
12181243& restrictinfo -> eval_cost );
12191244}
1220- total += restrictinfo -> eval_cost ;
1245+ cost -> startup += restrictinfo -> eval_cost .startup ;
1246+ cost -> per_tuple += restrictinfo -> eval_cost .per_tuple ;
12211247}
12221248else
12231249{
12241250/* If it's a bare expression, must always do it the hard way */
1225- cost_qual_eval_walker (qual ,& total );
1251+ cost_qual_eval_walker (qual ,cost );
12261252}
12271253}
1228- return total ;
12291254}
12301255
12311256static bool
1232- cost_qual_eval_walker (Node * node ,Cost * total )
1257+ cost_qual_eval_walker (Node * node ,QualCost * total )
12331258{
12341259if (node == NULL )
12351260return false;
@@ -1246,43 +1271,96 @@ cost_qual_eval_walker(Node *node, Cost *total)
12461271if (IsA (node ,FuncExpr )||
12471272IsA (node ,OpExpr )||
12481273IsA (node ,DistinctExpr ))
1249- * total += cpu_operator_cost ;
1274+ {
1275+ total -> per_tuple += cpu_operator_cost ;
1276+ }
1277+ else if (IsA (node ,SubLink ))
1278+ {
1279+ /* This routine should not be applied to un-planned expressions */
1280+ elog (ERROR ,"cost_qual_eval: can't handle unplanned sub-select" );
1281+ }
12501282else if (IsA (node ,SubPlan ))
12511283{
12521284/*
1253- * A subplan node in an expression indicates that the
1254- * subplan will be executed on each evaluation, so charge
1255- * accordingly. (We assume that sub-selects that can be
1256- * executed as InitPlans have already been removed from
1257- * the expression.)
1285+ * A subplan node in an expression typically indicates that the
1286+ * subplan will be executed on each evaluation, so charge accordingly.
1287+ * (Sub-selects that can be executed as InitPlans have already been
1288+ * removed from the expression.)
1289+ *
1290+ * An exception occurs when we have decided we can implement the
1291+ * subplan by hashing.
12581292 *
1259- * NOTE: this logic should agree with the estimates used by
1260- * make_subplan() in plan/subselect.c.
12611293 */
12621294SubPlan * subplan = (SubPlan * )node ;
12631295Plan * plan = subplan -> plan ;
1264- Cost subcost ;
12651296
1266- if (subplan -> subLinkType == EXISTS_SUBLINK )
1297+ if (subplan -> useHashTable )
12671298{
1268- /* we only need to fetch 1 tuple */
1269- subcost = plan -> startup_cost +
1270- (plan -> total_cost - plan -> startup_cost ) /plan -> plan_rows ;
1271- }
1272- else if (subplan -> subLinkType == ALL_SUBLINK ||
1273- subplan -> subLinkType == ANY_SUBLINK )
1274- {
1275- /* assume we need 50% of the tuples */
1276- subcost = plan -> startup_cost +
1277- 0.50 * (plan -> total_cost - plan -> startup_cost );
1278- /* XXX what if subplan has been materialized? */
1299+ /*
1300+ * If we are using a hash table for the subquery outputs, then
1301+ * the cost of evaluating the query is a one-time cost.
1302+ * We charge one cpu_operator_cost per tuple for the work of
1303+ * loading the hashtable, too.
1304+ */
1305+ total -> startup += plan -> total_cost +
1306+ cpu_operator_cost * plan -> plan_rows ;
1307+ /*
1308+ * The per-tuple costs include the cost of evaluating the
1309+ * lefthand expressions, plus the cost of probing the hashtable.
1310+ * Recursion into the exprs list will handle the lefthand
1311+ * expressions properly, and will count one cpu_operator_cost
1312+ * for each comparison operator. That is probably too low for
1313+ * the probing cost, but it's hard to make a better estimate,
1314+ * so live with it for now.
1315+ */
12791316}
12801317else
12811318{
1282- /* assume we need all tuples */
1283- subcost = plan -> total_cost ;
1319+ /*
1320+ * Otherwise we will be rescanning the subplan output on each
1321+ * evaluation. We need to estimate how much of the output
1322+ * we will actually need to scan. NOTE: this logic should
1323+ * agree with the estimates used by make_subplan() in
1324+ * plan/subselect.c.
1325+ */
1326+ Cost plan_run_cost = plan -> total_cost - plan -> startup_cost ;
1327+
1328+ if (subplan -> subLinkType == EXISTS_SUBLINK )
1329+ {
1330+ /* we only need to fetch 1 tuple */
1331+ total -> per_tuple += plan_run_cost /plan -> plan_rows ;
1332+ }
1333+ else if (subplan -> subLinkType == ALL_SUBLINK ||
1334+ subplan -> subLinkType == ANY_SUBLINK )
1335+ {
1336+ /* assume we need 50% of the tuples */
1337+ total -> per_tuple += 0.50 * plan_run_cost ;
1338+ /* also charge a cpu_operator_cost per row examined */
1339+ total -> per_tuple += 0.50 * plan -> plan_rows * cpu_operator_cost ;
1340+ }
1341+ else
1342+ {
1343+ /* assume we need all tuples */
1344+ total -> per_tuple += plan_run_cost ;
1345+ }
1346+ /*
1347+ * Also account for subplan's startup cost.
1348+ * If the subplan is uncorrelated or undirect correlated,
1349+ * AND its topmost node is a Sort or Material node, assume
1350+ * that we'll only need to pay its startup cost once;
1351+ * otherwise assume we pay the startup cost every time.
1352+ */
1353+ if (subplan -> parParam == NIL &&
1354+ (IsA (plan ,Sort )||
1355+ IsA (plan ,Material )))
1356+ {
1357+ total -> startup += plan -> startup_cost ;
1358+ }
1359+ else
1360+ {
1361+ total -> per_tuple += plan -> startup_cost ;
1362+ }
12841363}
1285- * total += subcost ;
12861364}
12871365
12881366return expression_tree_walker (node ,cost_qual_eval_walker ,
@@ -1388,7 +1466,7 @@ set_baserel_size_estimates(Query *root, RelOptInfo *rel)
13881466
13891467rel -> rows = temp ;
13901468
1391- rel -> baserestrictcost = cost_qual_eval ( rel -> baserestrictinfo );
1469+ cost_qual_eval ( & rel -> baserestrictcost , rel -> baserestrictinfo );
13921470
13931471set_rel_width (root ,rel );
13941472}
@@ -1533,7 +1611,7 @@ set_function_size_estimates(Query *root, RelOptInfo *rel)
15331611
15341612rel -> rows = temp ;
15351613
1536- rel -> baserestrictcost = cost_qual_eval ( rel -> baserestrictinfo );
1614+ cost_qual_eval ( & rel -> baserestrictcost , rel -> baserestrictinfo );
15371615
15381616set_rel_width (root ,rel );
15391617}