diff options
| author | Tom Lane <tgl@sss.pgh.pa.us> | 2007-05-21 17:57:35 +0000 |
|---|---|---|
| committer | Tom Lane <tgl@sss.pgh.pa.us> | 2007-05-21 17:57:35 +0000 |
| commit | 2415ad983174164ff30ce487c0e6b4b53321b83a (patch) | |
| tree | 8f3bae7fd588a6cfa9bcaf33e6e5ea5f1cf89a4d /src/backend/optimizer/plan/createplan.c | |
| parent | 3963574d13383b4f377ab054e47e4af20cb75e7d (diff) | |
Teach tuplestore.c to throw away data before the "mark" point when the caller
is using mark/restore but not rewind or backward-scan capability. Insert a
materialize plan node between a mergejoin and its inner child if the inner
child is a sort that is expected to spill to disk. The materialize shields
the sort from the need to do mark/restore and thereby allows it to perform
its final merge pass on-the-fly; while the materialize itself is normally
cheap since it won't spill to disk unless the number of tuples with equal
key values exceeds work_mem.
Greg Stark, with some kibitzing from Tom Lane.
Diffstat (limited to 'src/backend/optimizer/plan/createplan.c')
| -rw-r--r-- | src/backend/optimizer/plan/createplan.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index be0162406bd..23099df6dc3 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.230 2007/05/04 01:13:44 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.231 2007/05/21 17:57:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1601,6 +1601,30 @@ create_mergejoin_plan(PlannerInfo *root, innerpathkeys = best_path->jpath.innerjoinpath->pathkeys; /* + * If inner plan is a sort that is expected to spill to disk, add a + * materialize node to shield it from the need to handle mark/restore. + * This will allow it to perform the last merge pass on-the-fly, while + * in most cases not requiring the materialize to spill to disk. + * + * XXX really, Sort oughta do this for itself, probably, to avoid the + * overhead of a separate plan node. + */ + if (IsA(inner_plan, Sort) && + sort_exceeds_work_mem((Sort *) inner_plan)) + { + Plan *matplan = (Plan *) make_material(inner_plan); + + /* + * We assume the materialize will not spill to disk, and therefore + * charge just cpu_tuple_cost per tuple. + */ + copy_plan_costsize(matplan, inner_plan); + matplan->total_cost += cpu_tuple_cost * matplan->plan_rows; + + inner_plan = matplan; + } + + /* * Compute the opfamily/strategy/nullsfirst arrays needed by the executor. * The information is in the pathkeys for the two inputs, but we need to * be careful about the possibility of mergeclauses sharing a pathkey |
