Shouldn't cost_append() also scale the partial path's cost?

Started by Antonin Houskaover 2 years ago2 messages
#1Antonin Houska
ah@cybertec.at
1 attachment(s)

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

Attachments:

cost_append_scale_subpath_cost.difftext/x-diffDownload
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);
#2Kyotaro Horiguchi
horikyota.ntt@gmail.com
In reply to: Antonin Houska (#1)
Re: Shouldn't cost_append() also scale the partial path's cost?

At Wed, 14 Jun 2023 14:36:54 +0200, Antonin Houska <ah@cybertec.at> wrote in

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?

If I've got it right, the total cost of a partial seqscan path
comprises a distributed CPU run cost and an undistributed disk run
cost. If we want to adjust for a different worker number, we should
only tweak the CPU component of the total cost. By default, if one
page contains 100 rows (I guess a moderate ratio), these two costs are
balanced at a 1:1 ratio and the CPU run cost and disk run cost in a
partial seqscan path is 1:n (n = #workers). If we adjust the run cost
in the porposed manner, it adjusts the CPU run cost correctly but in
turn the disk run cost gets wrong (by a larger error in this premise).

In short, it will get wrong in a different way.

Actually it looks strange that rows are adjusted but cost is not, so
we might want to add an explanation in this aspect.

regards.

--
Kyotaro Horiguchi
NTT Open Source Software Center