Refactor create_limit_path() to share cost adjustment code with FDWs.
authorEtsuro Fujita <efujita@postgresql.org>
Tue, 2 Apr 2019 10:55:12 +0000 (19:55 +0900)
committerEtsuro Fujita <efujita@postgresql.org>
Tue, 2 Apr 2019 10:55:12 +0000 (19:55 +0900)
This is in preparation for an upcoming commit.

Author: Etsuro Fujita
Reviewed-By: Antonin Houska and Jeff Janes
Discussion: https://postgr.es/m/87pnz1aby9.fsf@news-spur.riddles.org.uk

src/backend/optimizer/util/pathnode.c
src/include/optimizer/pathnode.h

index 56de8fc370aafb413ad8d29702aef7ac3d36574a..1ea89ff54c984d06444bc0858cf83bcc89059c2e 100644 (file)
@@ -3578,17 +3578,42 @@ create_limit_path(PlannerInfo *root, RelOptInfo *rel,
 
    /*
     * Adjust the output rows count and costs according to the offset/limit.
-    * This is only a cosmetic issue if we are at top level, but if we are
-    * building a subquery then it's important to report correct info to the
-    * outer planner.
-    *
-    * When the offset or count couldn't be estimated, use 10% of the
-    * estimated number of rows emitted from the subpath.
-    *
-    * XXX we don't bother to add eval costs of the offset/limit expressions
-    * themselves to the path costs.  In theory we should, but in most cases
-    * those expressions are trivial and it's just not worth the trouble.
     */
+   adjust_limit_rows_costs(&pathnode->path.rows,
+                           &pathnode->path.startup_cost,
+                           &pathnode->path.total_cost,
+                           offset_est, count_est);
+
+   return pathnode;
+}
+
+/*
+ * adjust_limit_rows_costs
+ *   Adjust the size and cost estimates for a LimitPath node according to the
+ *   offset/limit.
+ *
+ * This is only a cosmetic issue if we are at top level, but if we are
+ * building a subquery then it's important to report correct info to the outer
+ * planner.
+ *
+ * When the offset or count couldn't be estimated, use 10% of the estimated
+ * number of rows emitted from the subpath.
+ *
+ * XXX we don't bother to add eval costs of the offset/limit expressions
+ * themselves to the path costs.  In theory we should, but in most cases those
+ * expressions are trivial and it's just not worth the trouble.
+ */
+void
+adjust_limit_rows_costs(double *rows,  /* in/out parameter */
+                       Cost *startup_cost, /* in/out parameter */
+                       Cost *total_cost,   /* in/out parameter */
+                       int64 offset_est,
+                       int64 count_est)
+{
+   double      input_rows = *rows;
+   Cost        input_startup_cost = *startup_cost;
+   Cost        input_total_cost = *total_cost;
+
    if (offset_est != 0)
    {
        double      offset_rows;
@@ -3596,16 +3621,16 @@ create_limit_path(PlannerInfo *root, RelOptInfo *rel,
        if (offset_est > 0)
            offset_rows = (double) offset_est;
        else
-           offset_rows = clamp_row_est(subpath->rows * 0.10);
-       if (offset_rows > pathnode->path.rows)
-           offset_rows = pathnode->path.rows;
-       if (subpath->rows > 0)
-           pathnode->path.startup_cost +=
-               (subpath->total_cost - subpath->startup_cost)
-               * offset_rows / subpath->rows;
-       pathnode->path.rows -= offset_rows;
-       if (pathnode->path.rows < 1)
-           pathnode->path.rows = 1;
+           offset_rows = clamp_row_est(input_rows * 0.10);
+       if (offset_rows > *rows)
+           offset_rows = *rows;
+       if (input_rows > 0)
+           *startup_cost +=
+               (input_total_cost - input_startup_cost)
+               * offset_rows / input_rows;
+       *rows -= offset_rows;
+       if (*rows < 1)
+           *rows = 1;
    }
 
    if (count_est != 0)
@@ -3615,19 +3640,17 @@ create_limit_path(PlannerInfo *root, RelOptInfo *rel,
        if (count_est > 0)
            count_rows = (double) count_est;
        else
-           count_rows = clamp_row_est(subpath->rows * 0.10);
-       if (count_rows > pathnode->path.rows)
-           count_rows = pathnode->path.rows;
-       if (subpath->rows > 0)
-           pathnode->path.total_cost = pathnode->path.startup_cost +
-               (subpath->total_cost - subpath->startup_cost)
-               * count_rows / subpath->rows;
-       pathnode->path.rows = count_rows;
-       if (pathnode->path.rows < 1)
-           pathnode->path.rows = 1;
+           count_rows = clamp_row_est(input_rows * 0.10);
+       if (count_rows > *rows)
+           count_rows = *rows;
+       if (input_rows > 0)
+           *total_cost = *startup_cost +
+               (input_total_cost - input_startup_cost)
+               * count_rows / input_rows;
+       *rows = count_rows;
+       if (*rows < 1)
+           *rows = 1;
    }
-
-   return pathnode;
 }
 
 
index 3a803b3fd0087a511df53bc1912d981654fab58a..5b577c12eca65c0d44bcb53589e6b4b93b87bd25 100644 (file)
@@ -265,6 +265,9 @@ extern LimitPath *create_limit_path(PlannerInfo *root, RelOptInfo *rel,
                  Path *subpath,
                  Node *limitOffset, Node *limitCount,
                  int64 offset_est, int64 count_est);
+extern void adjust_limit_rows_costs(double *rows,
+                       Cost *startup_cost, Cost *total_cost,
+                       int64 offset_est, int64 count_est);
 
 extern Path *reparameterize_path(PlannerInfo *root, Path *path,
                    Relids required_outer,