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

   ## Which issue does this PR close?
   
   None filed. Found while checking whether AQE can hold several broadcast 
joins in one stage — it can (q5 stage 3 and q8 stage 4 each hold four), but q7 
splits two apart and runs the second one single-threaded.
   
   ## Rationale for this change
   
   The `CollectLeft` arm of `SelectJoinRule` puts a multi-partition build side 
behind a broadcast exchange, which becomes a stage of its own. That pays off 
only when the probe is partitioned as well:
   
   - A **single-partition build** needs no stage — every task can read it in 
place.
   - A **single-partition probe** pins the join to one task whatever the build 
does, so the stage buys nothing.
   
   And the stage is not free. The build/probe choice comes from a size 
comparison, and AQE replans after every stage completion, so a later round can 
see statistics the first round did not have and answer that comparison the 
other way — swapping the inputs. The exchange created by the first answer is 
already a stage by then, and it is now on the **probe** side, where a broadcast 
read exposes a single partition. Everything above it collapses into one task.
   
   TPC-H q7 hit exactly this. Its stage 5 read 1.46 M rows through one task, 
running the `nation` join, the projection and the partial aggregate 
single-threaded while 15 partitions of input sat ready:
   
   ```
   -- before: stage 5, 1 task, task_ms 39
   AggregateExec: mode=Partial, gby=[supp_nation, cust_nation, l_year]
     HashJoinExec: mode=CollectLeft, on=[(n_nationkey@0, c_nationkey@3)], 
filter=...
       FilterExec: n_name = GERMANY OR n_name = FRANCE
         DataSourceExec: file_groups={1}
       ShuffleReaderExec: upstream_stage: 4, broadcast: true, 
upstream_partition_count: 16
   ```
   
   I confirmed the sequence by instrumenting the rule: the broadcast exchange 
is created once, from the branch that wraps a multi-partition build side, and 
the same join's swap decision is logged twice with opposite answers in the same 
query — `swap=Ok(false)` then `swap=Ok(true)` — as the estimates change between 
rounds.
   
   ## What changes are included in this PR?
   
   One guard, extracted as `broadcast_build_side_pays_off`: wrap the build side 
only when both sides have more than one partition. With it, q7's swap puts 
`nation` on the build side, the probe keeps its 16 partitions, and no exchange 
is planted:
   
   ```
   -- after: stage 5, 4 tasks, task_ms 10/13/14
       ShuffleReaderExec: upstream_stage: 4, partitioning: Hash([l_orderkey@3], 
16)
   ```
   
   ## Are these changes tested?
   
   A unit test covers the three cases of the predicate (both sides partitioned, 
single-partition probe, single-partition build). Full `ballista-scheduler` 
suite passes (363 + 25); clippy clean.
   
   End to end on TPC-H SF10, one scheduler and two executors x 4 vcores, AQE 
with `collect_statistics=true` and packing on:
   
   | | before | after |
   | --- | --- | --- |
   | q7 stage 5 | 1 task, `broadcast: true`, 1.46 M rows | 4 tasks, 
`Hash([l_orderkey@3], 16)` |
   | q7 job time | 1777 ms | 1249 ms (-30%) |
   | q7 broadcast readers | 1 | 0 |
   
   All 22 queries return identical row counts, and the other 21 plans are 
unchanged — same stage counts, same broadcast-reader counts — so the guard is 
confined to the case it describes.
   
   **Draft** for two reasons. The machine was running another workload during 
these measurements, so treat the -30% as indicative rather than precise; a 
clean run (ideally at SF1000, where the collapsed stage would carry ~150 M rows 
through one core) is worth having before merge. And q8 keeps three broadcast 
readers with this guard: the same collapse shape appears there via chained 
dimension joins, so there is likely a second case to handle.
   
   ## Are there any user-facing changes?
   
   No API or configuration change. One fewer stage boundary and more 
parallelism in plans that join a partitioned input against a single-partition 
side.
   


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