Summary:
By following the same pattern as in the vanilla PG parallel scan node costing, the current implementation simply divides the `run_cost` by `parallel_divisor`, however, this naive approach doesn't reflect the execution very well on YB because of architectural performance characteristic differences.
Specifically, this revision incorporates the following aspects into cost computations:
* DocDB --> PG result transfer overhead
* Serial execution:
* The scan node receives the results in batches where each batch size is determined by combination of the `yb_fetch_size_limit` and `yb_fetch_row_limit` guc parameter values.
* Parallel execution:
* The table/index is split into chunks specified by rowid (`ybctid`) ranges based on the `yb_parallel_range_size` guc value upfront then each parallel worker processes one chunk at a time.
* "Chunk" (work unit) splitting overhead
* PG
* Zero overhead because PG can directly locate the lower/upper bound rows with { block#, offset } encoded in each rowid (`ctid`).
* YB
* Each chunk bounds are specified by adding conditions on the `ybctid`s. So, some of the cost components should not be divided because of parallelization:
* Per seek costs are unaffected because the seeks within each chunk is performed against the entire table/index.
* The first worker would take a hit on the disk read and others would benefit from cached data, but this doesn't help overall execution time because the first worker becomes the longest pole.
Jira: DB-14369
Test Plan:
./yb_build.sh release --java-test 'org.yb.pgsql.TestPgRegressParallel'
./yb_build.sh release --java-test 'org.yb.pgsql.TestPgRegressParallel2'
./yb_build.sh release --java-test 'org.yb.pgsql.TestPgRegressThirdPartyExtensionsPgHintPlan'
./yb_build.sh release --java-test 'org.yb.pgsql.TestPgRegressPlanner'
./yb_build.sh release --java-test 'org.yb.pgsql.TestPgRegressJoin'
Reviewers: amartsinchyk, gkukreja, mihnea
Reviewed By: amartsinchyk
Subscribers: rthallam, smishra, yql
Differential Revision: https://phorge.dev.yugabyte.com/D40495