coderfender opened a new issue, #26383:
URL: https://github.com/apache/datafusion/issues/26383

   ### Is your feature request related to a problem or challenge?
   
   `CrossJoinExec` buffers the **entire left input** in memory with no spill 
path, so a large left side can exhaust the memory pool even when the right side 
(and the useful working set) is tiny.
   
   In `datafusion/physical-plan/src/joins/cross_join.rs`, `load_left_input` 
folds all left batches into a `Vec`, growing a `MemoryReservation` per batch:
   
   ```rust
   async fn load_left_input(..., reservation: MemoryReservation, ...) {
       let (batches, _metrics, reservation) = stream
           .fold((Vec::new(), metrics, reservation), |(mut batches, metrics, 
reservation), batch| async {
               let batch_size = batch.get_array_memory_size();
               reservation.try_grow(batch_size)?;   // grow-or-error; no spill
               batches.push(batch);
               ...
           }).await?;
   }
   ```
   
   When the pool refuses `try_grow`, execution fails with `Resources exhausted: 
Additional allocation failed for CrossJoinExec ... can spill: false`. Unlike 
`SortExec` (and the recent sort-merge-join spill work), `CrossJoinExec` has no 
`SpillManager` fallback.
   
   **Reproduction** (observed via datafusion-comet, which delegates Spark 
`CartesianProductExec` to `CrossJoinExec`): a 1,000,000-row left range crossed 
with a 1-row right range under a ~4 MiB pool fails at its fair share, while 
engines that spill the buffered side (e.g. Spark's `UnsafeCartesianRDD`) 
complete and return the result. DataFusion 55.2.0's `load_left_input` confirms 
unconditional accumulation.
   
   ### Describe the solution you'd like
   
   Add a spill path to `CrossJoinExec` so the buffered left input can spill to 
disk when the reservation cannot grow, then re-read it from disk during probing 
— mirroring the approach `SortExec` and the sort-merge-join operator already 
use (`SpillManager` + on-disk runs). This would let cross joins over a large 
left input complete under memory pressure instead of erroring.
   
   ### Describe alternatives you've considered
   
   - Streaming the left and buffering/spilling the right instead (closer to 
Spark's model), though that changes which side is materialized.
   - Keeping the current behavior but documenting the unbounded-left-buffer 
limitation.
   
   ### Additional context
   
   Found while adding native cross-join support in apache/datafusion-comet 
(apache/datafusion-comet#6938); Comet currently gates that path as opt-in 
specifically because of this non-spillable buffering. Happy to work on this.
   


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