]> granicus.if.org Git - postgresql/commitdiff
Adjust costsize calculations to avoid introducing unnecessary roundoff
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 13 Dec 2002 17:29:25 +0000 (17:29 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 13 Dec 2002 17:29:25 +0000 (17:29 +0000)
error.  This seems to explain the differing choice of plan that's been
causing geometry regress test to fail for the last few days.

src/backend/optimizer/path/costsize.c

index 2125ff034f3644f52f80b6cedf810d06042b1a79..114e879885639d06ef5403b412abaf2f83f2e177 100644 (file)
@@ -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.94 2002/12/12 15:49:28 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.95 2002/12/13 17:29:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -672,12 +672,22 @@ cost_nestloop(Path *path, Query *root,
         */
        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 (!(IsA(inner_path, MaterialPath) ||
-                 IsA(inner_path, HashPath)) &&
-               outer_path->parent->rows > 1)
-               run_cost += (outer_path->parent->rows - 1) * inner_path->startup_cost;
+       if (IsA(inner_path, MaterialPath) ||
+               IsA(inner_path, HashPath))
+       {
+               /* charge only run cost for each iteration of inner path */
+               run_cost += outer_path->parent->rows *
+                       (inner_path->total_cost - inner_path->startup_cost);
+       }
+       else
+       {
+               /*
+                * charge total cost for each iteration of inner path, except we
+                * already charged the first startup_cost in our own startup
+                */
+               run_cost += outer_path->parent->rows * inner_path->total_cost
+                       - inner_path->startup_cost;
+       }
 
        /*
         * Number of tuples processed (not number emitted!).  If inner path is
@@ -768,8 +778,8 @@ cost_mergejoin(Path *path, Query *root,
                innerscansel = firstclause->left_mergescansel;
        }
 
-       outer_rows = outer_path->parent->rows * outerscansel;
-       inner_rows = inner_path->parent->rows * innerscansel;
+       outer_rows = ceil(outer_path->parent->rows * outerscansel);
+       inner_rows = ceil(inner_path->parent->rows * innerscansel);
 
        /* cost of source data */
 
@@ -1343,10 +1353,12 @@ approx_selectivity(Query *root, List *quals)
 void
 set_baserel_size_estimates(Query *root, RelOptInfo *rel)
 {
+       double          temp;
+
        /* Should only be applied to base relations */
        Assert(length(rel->relids) == 1);
 
-       rel->rows = rel->tuples *
+       temp = rel->tuples *
                restrictlist_selectivity(root,
                                                                 rel->baserestrictinfo,
                                                                 lfirsti(rel->relids));
@@ -1354,10 +1366,14 @@ set_baserel_size_estimates(Query *root, RelOptInfo *rel)
        /*
         * Force estimate to be at least one row, to make explain output look
         * better and to avoid possible divide-by-zero when interpolating
-        * cost.
+        * cost.  Make it an integer, too.
         */
-       if (rel->rows < 1.0)
-               rel->rows = 1.0;
+       if (temp < 1.0)
+               temp = 1.0;
+       else
+               temp = ceil(temp);
+
+       rel->rows = temp;
 
        rel->baserestrictcost = cost_qual_eval(rel->baserestrictinfo);
 
@@ -1437,10 +1453,12 @@ set_joinrel_size_estimates(Query *root, RelOptInfo *rel,
        /*
         * Force estimate to be at least one row, to make explain output look
         * better and to avoid possible divide-by-zero when interpolating
-        * cost.
+        * cost.  Make it an integer, too.
         */
        if (temp < 1.0)
                temp = 1.0;
+       else
+               temp = ceil(temp);
 
        rel->rows = temp;
 
@@ -1470,6 +1488,8 @@ set_joinrel_size_estimates(Query *root, RelOptInfo *rel,
 void
 set_function_size_estimates(Query *root, RelOptInfo *rel)
 {
+       double          temp;
+
        /* Should only be applied to base relations that are functions */
        Assert(length(rel->relids) == 1);
        Assert(rel->rtekind == RTE_FUNCTION);
@@ -1483,7 +1503,7 @@ set_function_size_estimates(Query *root, RelOptInfo *rel)
        rel->tuples = 1000;
 
        /* Now estimate number of output rows */
-       rel->rows = rel->tuples *
+       temp = rel->tuples *
                restrictlist_selectivity(root,
                                                                 rel->baserestrictinfo,
                                                                 lfirsti(rel->relids));
@@ -1491,10 +1511,14 @@ set_function_size_estimates(Query *root, RelOptInfo *rel)
        /*
         * Force estimate to be at least one row, to make explain output look
         * better and to avoid possible divide-by-zero when interpolating
-        * cost.
+        * cost.  Make it an integer, too.
         */
-       if (rel->rows < 1.0)
-               rel->rows = 1.0;
+       if (temp < 1.0)
+               temp = 1.0;
+       else
+               temp = ceil(temp);
+
+       rel->rows = temp;
 
        rel->baserestrictcost = cost_qual_eval(rel->baserestrictinfo);