|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.146 2008/08/14 18:47:59 tgl Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.147 2008/09/05 21:07:29 tgl Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -1304,19 +1304,43 @@ create_mergejoin_path(PlannerInfo *root,
|
1304 | 1304 |
|
1305 | 1305 | /*
|
1306 | 1306 | * If we are not sorting the inner path, we may need a materialize node to
|
1307 |
| - * ensure it can be marked/restored. (Sort does support mark/restore, so |
1308 |
| - * no materialize is needed in that case.) |
| 1307 | + * ensure it can be marked/restored. |
1309 | 1308 | *
|
1310 | 1309 | * Since the inner side must be ordered, and only Sorts and IndexScans can
|
1311 |
| - * create order to begin with, you might think there's no problem --- but |
1312 |
| - * you'd be wrong. Nestloop and merge joins can *preserve* the order of |
1313 |
| - * their inputs, so they can be selected as the input of a mergejoin, and |
1314 |
| - * they don't support mark/restore at present. |
| 1310 | + * create order to begin with, and they both support mark/restore, you |
| 1311 | + * might think there's no problem --- but you'd be wrong. Nestloop and |
| 1312 | + * merge joins can *preserve* the order of their inputs, so they can be |
| 1313 | + * selected as the input of a mergejoin, and they don't support |
| 1314 | + * mark/restore at present. |
| 1315 | + * |
| 1316 | + * Note: Sort supports mark/restore, so no materialize is really needed |
| 1317 | + * in that case; but one may be desirable anyway to optimize the sort. |
| 1318 | + * However, since we aren't representing the sort step separately in |
| 1319 | + * the Path tree, we can't explicitly represent the materialize either. |
| 1320 | + * So that case is not handled here. Instead, cost_mergejoin has to |
| 1321 | + * factor in the cost and create_mergejoin_plan has to add the plan node. |
1315 | 1322 | */
|
1316 | 1323 | if (innersortkeys == NIL &&
|
1317 | 1324 | !ExecSupportsMarkRestore(inner_path->pathtype))
|
1318 |
| - inner_path = (Path *) |
1319 |
| - create_material_path(inner_path->parent, inner_path); |
| 1325 | + { |
| 1326 | + Path *mpath; |
| 1327 | + |
| 1328 | + mpath = (Path *) create_material_path(inner_path->parent, inner_path); |
| 1329 | + |
| 1330 | + /* |
| 1331 | + * We expect the materialize won't spill to disk (it could only do |
| 1332 | + * so if there were a whole lot of duplicate tuples, which is a case |
| 1333 | + * cost_mergejoin will avoid choosing anyway). Therefore |
| 1334 | + * cost_material's cost estimate is bogus and we should charge |
| 1335 | + * just cpu_tuple_cost per tuple. (Keep this estimate in sync with |
| 1336 | + * similar ones in cost_mergejoin and create_mergejoin_plan.) |
| 1337 | + */ |
| 1338 | + mpath->startup_cost = inner_path->startup_cost; |
| 1339 | + mpath->total_cost = inner_path->total_cost; |
| 1340 | + mpath->total_cost += cpu_tuple_cost * inner_path->parent->rows; |
| 1341 | + |
| 1342 | + inner_path = mpath; |
| 1343 | + } |
1320 | 1344 |
|
1321 | 1345 | pathnode->jpath.path.pathtype = T_MergeJoin;
|
1322 | 1346 | pathnode->jpath.path.parent = joinrel;
|
|
0 commit comments