]> granicus.if.org Git - postgresql/commitdiff
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,