Like in cost_seqscan(), I'd expect the subpath cost to be divided among
parallel workers. The patch below shows what I mean. Am I right?
--
Antonin Houska
Web: https://www.cybertec-postgresql.com
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index ef475d95a1..5427822e0e 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -2313,19 +2313,29 @@ cost_append(AppendPath *apath)
* Apply parallel divisor to subpaths. Scale the number of rows
* for each partial subpath based on the ratio of the parallel
* divisor originally used for the subpath to the one we adopted.
- * Also add the cost of partial paths to the total cost, but
- * ignore non-partial paths for now.
+ * Also add the scaled cost of partial paths to the total cost,
+ * but ignore non-partial paths for now.
*/
if (i < apath->first_partial_path)
apath->path.rows += subpath->rows / parallel_divisor;
else
{
double subpath_parallel_divisor;
+ double scale_factor;
+ Cost run_cost;
subpath_parallel_divisor = get_parallel_divisor(subpath);
- apath->path.rows += subpath->rows * (subpath_parallel_divisor /
- parallel_divisor);
- apath->path.total_cost += subpath->total_cost;
+ scale_factor = subpath_parallel_divisor / parallel_divisor;
+ apath->path.rows += subpath->rows * scale_factor;
+ /*
+ * XXX run_cost includes both CPU cost, which is divided among
+ * workers, and disk cost, which is not. Unfortunately we
+ * don't have enough information to separate the two, so scale
+ * the whole run_cost.
+ */
+ run_cost = subpath->total_cost - subpath->startup_cost;
+ apath->path.total_cost += subpath->startup_cost +
+ run_cost * scale_factor;;
}
apath->path.rows = clamp_row_est(apath->path.rows);