NoahKusaba opened a new issue, #2454:
URL: https://github.com/apache/datafusion-ballista/issues/2454

   **Is your feature request related to a problem or challenge? Please describe 
what you are trying to do.**
   
   Found while analysing TPC-H q8 at SF1000 in #2419.
   
   AQE plans a broadcast from *estimated* statistics. If the broadcast side 
then *measures* larger, the replan's `join_selection` swaps the `CollectLeft` 
join. The broadcast `ExchangeExec` lands on the **probe** side but still 
reports one partition, so the join stage runs as a single task. In q8, ~80M 
probe rows went through one task.
   
   Repro shape: `guessed_small`, estimated at 10 MB and broadcast, joined with 
`mid`, a known 500 MB. `guessed_small`'s stage then reports 8 GB, and the 
replan swaps it onto the probe side. Expected join stage:
   
   ```
   ShuffleWriterExec: partitioning: UnknownPartitioning(4)
     HashJoinExec: mode=CollectLeft, join_type=Inner, on=[(id@0, id@0)], 
projection=[val@2]
       CoalescePartitionsExec
         ShuffleReaderExec: upstream_stage: 1, partitioning: 
UnknownPartitioning(4)
       ShuffleReaderExec: upstream_stage: 0, partitioning: 
UnknownPartitioning(4)
   ```
   
   **Describe the solution you'd like**
   
   Add a hook to DataFusion's `ExecutionPlan`, which `join_selection` calls on 
the input it moves to the probe side during a `CollectLeft` swap:
   
   ```rust
   fn as_probe_side(&self) -> Result<Option<Arc<dyn ExecutionPlan>>> { Ok(None) 
}
   ```
   
   Ballista implements it on `ExchangeExec`, so no extra optimizer rule is 
needed:
   
   ```rust
   fn as_probe_side(&self) -> Result<Option<Arc<dyn ExecutionPlan>>> {
       if !self.broadcast || 
self.input.properties().output_ordering().is_some() {
           return Ok(None);
       }
       Ok(Some(Arc::new(self.to_partitioned())))
   }
   ```
   
   The fix happens at the swap itself, with no rule ordering to get right. It 
has been prototyped against DataFusion `main` and passes the probe-side tests 
in Ballista. It needs an upstream DataFusion PR and a Ballista upgrade to a 
release that includes it.
   
   **Describe alternatives you've considered**
   
   - **Ballista-only rule.** Run a rule after `join_selection` that replaces a 
broadcast `ExchangeExec` on a `CollectLeft` probe side with `to_partitioned()`. 
It works on the current DataFusion, so it could bridge until the hook lands. 
However, it repairs the plan after the swap and depends on where it sits in the 
rule order.
   - **Remove `ExchangeExec`'s `broadcast` flag.** Derive broadcast from the 
exchange's side of the join, so a swap can't misplace it. Cleanest, but a 
larger refactor.
   
   **Additional context**
   
   - Null-aware anti joins (#2198) and broadcasts over ordered inputs must keep 
a single partition.
   - Related: #2434, #2024, #2121.
   


-- 
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