42
42
* Portions Copyright (c) 1994, Regents of the University of California
43
43
*
44
44
* 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 $
46
46
*
47
47
*-------------------------------------------------------------------------
48
48
*/
@@ -87,7 +87,7 @@ bool enable_hashjoin = true;
87
87
88
88
static Selectivity estimate_hash_bucketsize (Query * root , Var * var ,
89
89
int nbuckets );
90
- static bool cost_qual_eval_walker (Node * node , Cost * total );
90
+ static bool cost_qual_eval_walker (Node * node , QualCost * total );
91
91
static Selectivity approx_selectivity (Query * root , List * quals );
92
92
static void set_rel_width (Query * root , RelOptInfo * rel );
93
93
static double relation_byte_size (double tuples , int width );
@@ -131,7 +131,8 @@ cost_seqscan(Path *path, Query *root,
131
131
run_cost += baserel -> pages ; /* sequential fetches with cost 1.0 */
132
132
133
133
/* 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 ;
135
136
run_cost += cpu_per_tuple * baserel -> tuples ;
136
137
137
138
path -> startup_cost = startup_cost ;
@@ -344,17 +345,25 @@ cost_index(Path *path, Query *root,
344
345
*
345
346
* Normally the indexquals will be removed from the list of restriction
346
347
* 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.
353
356
*/
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 ;
355
359
356
360
if (!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
+ }
358
367
359
368
run_cost += cpu_per_tuple * tuples_fetched ;
360
369
@@ -386,7 +395,8 @@ cost_tidscan(Path *path, Query *root,
386
395
run_cost += random_page_cost * ntuples ;
387
396
388
397
/* 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 ;
390
400
run_cost += cpu_per_tuple * ntuples ;
391
401
392
402
path -> startup_cost = startup_cost ;
@@ -416,7 +426,8 @@ cost_functionscan(Path *path, Query *root, RelOptInfo *baserel)
416
426
cpu_per_tuple = cpu_operator_cost ;
417
427
418
428
/* 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 ;
420
431
run_cost += cpu_per_tuple * baserel -> tuples ;
421
432
422
433
path -> startup_cost = startup_cost ;
@@ -656,6 +667,7 @@ cost_nestloop(Path *path, Query *root,
656
667
Cost startup_cost = 0 ;
657
668
Cost run_cost = 0 ;
658
669
Cost cpu_per_tuple ;
670
+ QualCost restrict_qual_cost ;
659
671
double ntuples ;
660
672
661
673
if (!enable_nestloop )
@@ -703,7 +715,9 @@ cost_nestloop(Path *path, Query *root,
703
715
ntuples *= outer_path -> parent -> rows ;
704
716
705
717
/* 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 ;
707
721
run_cost += cpu_per_tuple * ntuples ;
708
722
709
723
path -> startup_cost = startup_cost ;
@@ -736,6 +750,7 @@ cost_mergejoin(Path *path, Query *root,
736
750
Cost startup_cost = 0 ;
737
751
Cost run_cost = 0 ;
738
752
Cost cpu_per_tuple ;
753
+ QualCost restrict_qual_cost ;
739
754
RestrictInfo * firstclause ;
740
755
Var * leftvar ;
741
756
double outer_rows ,
@@ -850,7 +865,9 @@ cost_mergejoin(Path *path, Query *root,
850
865
outer_path -> parent -> rows * inner_path -> parent -> rows ;
851
866
852
867
/* 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 ;
854
871
run_cost += cpu_per_tuple * ntuples ;
855
872
856
873
path -> startup_cost = startup_cost ;
@@ -878,6 +895,7 @@ cost_hashjoin(Path *path, Query *root,
878
895
Cost startup_cost = 0 ;
879
896
Cost run_cost = 0 ;
880
897
Cost cpu_per_tuple ;
898
+ QualCost restrict_qual_cost ;
881
899
double ntuples ;
882
900
double outerbytes = relation_byte_size (outer_path -> parent -> rows ,
883
901
outer_path -> parent -> width );
@@ -984,7 +1002,9 @@ cost_hashjoin(Path *path, Query *root,
984
1002
outer_path -> parent -> rows * inner_path -> parent -> rows ;
985
1003
986
1004
/* 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 ;
988
1008
run_cost += cpu_per_tuple * ntuples ;
989
1009
990
1010
/*
@@ -1185,16 +1205,20 @@ estimate_hash_bucketsize(Query *root, Var *var, int nbuckets)
1185
1205
1186
1206
/*
1187
1207
* cost_qual_eval
1188
- * Estimate the CPU cost of evaluating a WHERE clause (once) .
1208
+ * Estimate the CPU costs of evaluating a WHERE clause.
1189
1209
* The input can be either an implicitly-ANDed list of boolean
1190
1210
* expressions, or a list of RestrictInfo nodes.
1211
+ * The result includes both a one-time (startup) component,
1212
+ * and a per-evaluation component.
1191
1213
*/
1192
- Cost
1193
- cost_qual_eval (List * quals )
1214
+ void
1215
+ cost_qual_eval (QualCost * cost , List * quals )
1194
1216
{
1195
- Cost total = 0 ;
1196
1217
List * l ;
1197
1218
1219
+ cost -> startup = 0 ;
1220
+ cost -> per_tuple = 0 ;
1221
+
1198
1222
/* We don't charge any cost for the implicit ANDing at top level ... */
1199
1223
1200
1224
foreach (l , quals )
@@ -1205,31 +1229,32 @@ cost_qual_eval(List *quals)
1205
1229
* RestrictInfo nodes contain an eval_cost field reserved for this
1206
1230
* routine's use, so that it's not necessary to evaluate the qual
1207
1231
* 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.
1209
1233
*/
1210
1234
if (qual && IsA (qual , RestrictInfo ))
1211
1235
{
1212
1236
RestrictInfo * restrictinfo = (RestrictInfo * ) qual ;
1213
1237
1214
- if (restrictinfo -> eval_cost < 0 )
1238
+ if (restrictinfo -> eval_cost . startup < 0 )
1215
1239
{
1216
- restrictinfo -> eval_cost = 0 ;
1240
+ restrictinfo -> eval_cost .startup = 0 ;
1241
+ restrictinfo -> eval_cost .per_tuple = 0 ;
1217
1242
cost_qual_eval_walker ((Node * ) restrictinfo -> clause ,
1218
1243
& restrictinfo -> eval_cost );
1219
1244
}
1220
- total += restrictinfo -> eval_cost ;
1245
+ cost -> startup += restrictinfo -> eval_cost .startup ;
1246
+ cost -> per_tuple += restrictinfo -> eval_cost .per_tuple ;
1221
1247
}
1222
1248
else
1223
1249
{
1224
1250
/* 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 );
1226
1252
}
1227
1253
}
1228
- return total ;
1229
1254
}
1230
1255
1231
1256
static bool
1232
- cost_qual_eval_walker (Node * node , Cost * total )
1257
+ cost_qual_eval_walker (Node * node , QualCost * total )
1233
1258
{
1234
1259
if (node == NULL )
1235
1260
return false;
@@ -1246,43 +1271,96 @@ cost_qual_eval_walker(Node *node, Cost *total)
1246
1271
if (IsA (node , FuncExpr ) ||
1247
1272
IsA (node , OpExpr ) ||
1248
1273
IsA (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
+ }
1250
1282
else if (IsA (node , SubPlan ))
1251
1283
{
1252
1284
/*
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.
1258
1292
*
1259
- * NOTE: this logic should agree with the estimates used by
1260
- * make_subplan() in plan/subselect.c.
1261
1293
*/
1262
1294
SubPlan * subplan = (SubPlan * ) node ;
1263
1295
Plan * plan = subplan -> plan ;
1264
- Cost subcost ;
1265
1296
1266
- if (subplan -> subLinkType == EXISTS_SUBLINK )
1297
+ if (subplan -> useHashTable )
1267
1298
{
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
+ */
1279
1316
}
1280
1317
else
1281
1318
{
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
+ }
1284
1363
}
1285
- * total += subcost ;
1286
1364
}
1287
1365
1288
1366
return expression_tree_walker (node , cost_qual_eval_walker ,
@@ -1388,7 +1466,7 @@ set_baserel_size_estimates(Query *root, RelOptInfo *rel)
1388
1466
1389
1467
rel -> rows = temp ;
1390
1468
1391
- rel -> baserestrictcost = cost_qual_eval ( rel -> baserestrictinfo );
1469
+ cost_qual_eval ( & rel -> baserestrictcost , rel -> baserestrictinfo );
1392
1470
1393
1471
set_rel_width (root , rel );
1394
1472
}
@@ -1533,7 +1611,7 @@ set_function_size_estimates(Query *root, RelOptInfo *rel)
1533
1611
1534
1612
rel -> rows = temp ;
1535
1613
1536
- rel -> baserestrictcost = cost_qual_eval ( rel -> baserestrictinfo );
1614
+ cost_qual_eval ( & rel -> baserestrictcost , rel -> baserestrictinfo );
1537
1615
1538
1616
set_rel_width (root , rel );
1539
1617
}
0 commit comments