andygrove opened a new pull request, #2186:
URL: https://github.com/apache/datafusion-ballista/pull/2186

   # Which issue does this PR close?
   
   Closes #2184.
   
   # Rationale for this change
   
   Per-task restriction gives each branch of a `UnionExec` the partitions that 
task owns and an empty slice to the rest, relying on an unowned branch becoming 
0-partition so the union's index arithmetic routes past it.
   
   That fails when a branch's partition count does not come from restrictable 
leaves. A `CoalescePartitionsExec` or a non-preserving `SortExec` reports one 
partition whatever its leaves do, and a broadcast `ShuffleReaderExec` is 
deliberately never pruned. The branch keeps reporting a partition and keeps 
producing all of its data, so the executor — which runs every partition of the 
plan it is handed — runs every branch for every task.
   
   At SF1 with `target_partitions=1`:
   
   | Query | Expected | Got | |
   |---|---|---|---|
   | q5 | `73724.99` | `294899.96` | 4x |
   | q80 | `11343.60` | `22687.20` | 2x |
   | q49 | — | `Internal("FileStreamBuilder invalid partition index: 0")` | |
   
   This does not show at higher partition counts because those union stages are 
capped by a hash repartition, where the writer's output is an intrinsic K-space 
and inner partition counts do not matter. Confirmed by instrumenting the 
rewriter: restricting q49's 3-partition union stage to `[0]` returned a plan 
that still had 3 partitions.
   
   # What changes are included in this PR?
   
   **`planner.rs` — cut a stage boundary beneath a union branch that cannot be 
restricted away.** The branch becomes a `ShuffleReaderExec`, which restricts to 
nothing cleanly, and the collapse moves into its own stage where it still sees 
its whole input. Branches that already restrict away stay inline, so a union of 
plain scans is unaffected and pays no extra shuffle.
   
   Whether a branch can be restricted away is decided by *asking the rewriter* 
(`restrict_plan_to_partitions(branch, &[])`) rather than by matching operator 
types, so it stays correct as the rewriter evolves.
   
   Branches holding a broadcast input or a `CollectLeft` join are treated as 
unrestrictable regardless. Those build and probe sides can still be swapped 
after stage planning, and the two orders restrict differently — the build side 
is read whole, a broadcast input is never pruned — so a branch that looks 
restrictable at planning time may not be by the time the task is built. That is 
exactly what left q5's catalog branch running in every task after the first 
version of this fix.
   
   **`task_builder.rs` — take restriction scope from 
`required_input_distribution()` for every operator** instead of a hardcoded 
list of join types. `CrossJoinExec` collects its left input but was not on that 
list, so each task of a multi-partition stage rebuilt the cross join's left 
side from its own slice. This surfaced as an inflated q77 (whose catalog branch 
is `from cs, cr`) once that branch got a stage of its own — caught by the 
full-suite run, not by the original repro.
   
   # Are there any user-facing changes?
   
   No API change. Union queries whose branches collapse internally now 
materialize those branches as their own stage, which costs one extra shuffle 
per affected branch and is what makes the result correct.
   
   ## Testing
   
   Four unit tests: a plain branch needs no stage of its own, a collapsing 
branch and a broadcast-holding branch do, and a cross join's collected side is 
read whole.
   
   End-to-end at SF1 against a single-process DataFusion oracle:
   
   - `--partitions 16` — **the full suite passes**, so the currently-green 
configuration is unaffected.
   - `--partitions 1` — q5, q49, q80, q61 and q77 all verify OK. Only q72 
remains, and it exhausts its per-task memory share rather than returning a 
wrong answer.
   
   ## Not covered
   
   The adaptive planner builds stages through its own path (`state/aqe/`) and 
is untouched here; q5, q80 and q61 still fail under 
`ballista.planner.adaptive.enabled=true` at one partition. #2185 stays open, 
and #2182 will still show the AQE legs red.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to