diff options
Diffstat (limited to 'src/backend/optimizer/path/costsize.c')
-rw-r--r-- | src/backend/optimizer/path/costsize.c | 57 |
1 files changed, 46 insertions, 11 deletions
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index fbdeea414c2..1db310fc52e 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -42,7 +42,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.92 2002/11/30 00:08:16 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.93 2002/11/30 05:21:02 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -230,7 +230,7 @@ cost_index(Path *path, Query *root, Assert(length(baserel->relids) == 1); Assert(baserel->rtekind == RTE_RELATION); - if (!enable_indexscan && !is_injoin) + if (!enable_indexscan) startup_cost += disable_cost; /* @@ -514,6 +514,43 @@ cost_sort(Path *path, Query *root, } /* + * cost_material + * Determines and returns the cost of materializing a relation, including + * the cost of reading the input data. + * + * If the total volume of data to materialize exceeds SortMem, we will need + * to write it to disk, so the cost is much higher in that case. + */ +void +cost_material(Path *path, + Cost input_cost, double tuples, int width) +{ + Cost startup_cost = input_cost; + Cost run_cost = 0; + double nbytes = relation_byte_size(tuples, width); + long sortmembytes = SortMem * 1024L; + + /* disk costs */ + if (nbytes > sortmembytes) + { + double npages = ceil(nbytes / BLCKSZ); + + /* We'll write during startup and read during retrieval */ + startup_cost += npages; + run_cost += npages; + } + + /* + * Also charge a small amount per extracted tuple. We use cpu_tuple_cost + * so that it doesn't appear worthwhile to materialize a bare seqscan. + */ + run_cost += cpu_tuple_cost * tuples; + + path->startup_cost = startup_cost; + path->total_cost = startup_cost + run_cost; +} + +/* * cost_agg * Determines and returns the cost of performing an Agg plan node, * including the cost of its input. @@ -630,19 +667,17 @@ cost_nestloop(Path *path, Query *root, * before we can start returning tuples, so the join's startup cost is * their sum. What's not so clear is whether the inner path's * startup_cost must be paid again on each rescan of the inner path. - * This is not true if the inner path is materialized, but probably is - * true otherwise. Since we don't yet have clean handling of the - * decision whether to materialize a path, we can't tell here which - * will happen. As a compromise, charge 50% of the inner startup cost - * for each restart. + * This is not true if the inner path is materialized or is a hashjoin, + * but probably is true otherwise. */ startup_cost += outer_path->startup_cost + inner_path->startup_cost; run_cost += outer_path->total_cost - outer_path->startup_cost; run_cost += outer_path->parent->rows * (inner_path->total_cost - inner_path->startup_cost); - if (outer_path->parent->rows > 1) - run_cost += (outer_path->parent->rows - 1) * - inner_path->startup_cost * 0.5; + if (!(IsA(inner_path, MaterialPath) || + IsA(inner_path, HashPath)) && + outer_path->parent->rows > 1) + run_cost += (outer_path->parent->rows - 1) * inner_path->startup_cost; /* * Number of tuples processed (not number emitted!). If inner path is @@ -1544,7 +1579,7 @@ set_rel_width(Query *root, RelOptInfo *rel) static double relation_byte_size(double tuples, int width) { - return tuples * ((double) MAXALIGN(width + sizeof(HeapTupleData))); + return tuples * (MAXALIGN(width) + MAXALIGN(sizeof(HeapTupleData))); } /* |