|
|
|
@ -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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|