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 | |
parent | 3963574d13383b4f377ab054e47e4af20cb75e7d (diff) | |
download | postgresql-2415ad983174164ff30ce487c0e6b4b53321b83a.tar.gz postgresql-2415ad983174164ff30ce487c0e6b4b53321b83a.zip |
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')
-rw-r--r-- | src/backend/optimizer/path/costsize.c | 19 | ||||
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 26 |
2 files changed, 43 insertions, 2 deletions
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 82dfc77f065..55c7648b9e7 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -54,7 +54,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.182 2007/05/04 01:13:44 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.183 2007/05/21 17:57:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1039,6 +1039,23 @@ cost_sort(Path *path, PlannerInfo *root, } /* + * sort_exceeds_work_mem + * Given a finished Sort plan node, detect whether it is expected to + * spill to disk (ie, will need more than work_mem workspace) + * + * This assumes there will be no available LIMIT. + */ +bool +sort_exceeds_work_mem(Sort *sort) +{ + double input_bytes = relation_byte_size(sort->plan.plan_rows, + sort->plan.plan_width); + long work_mem_bytes = work_mem * 1024L; + + return (input_bytes > work_mem_bytes); +} + +/* * cost_material * Determines and returns the cost of materializing a relation, including * the cost of reading the input data. 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 |