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

   ### Describe the bug
   
   `SortMergeJoinExec` charges a buffered batch twice for each join key that is 
a plain column. `BufferedBatch::try_new` adds `batch.get_array_memory_size()` 
and the size of each evaluated join key array. When the key is a column 
reference, the key array shares its buffers with the batch. The reservation 
then counts that column two times.
   
   Code: 
https://github.com/apache/datafusion/blob/34eb6dc5b/datafusion/physical-plan/src/joins/sort_merge_join/materializing_stream.rs#L289-L299
   
   The effect is that a join on a wide string key reserves about twice the 
memory it holds. This makes the join spill or fail under a memory limit earlier 
than it should.
   
   ### To Reproduce
   
   Run this in `datafusion-cli` (commit 34eb6dc5b on main). Both queries buffer 
the same data. Only the join key differs.
   
   ```sql
   SET datafusion.execution.target_partitions = 2;
   SET datafusion.optimizer.prefer_hash_join = false;
   CREATE TABLE l AS SELECT value AS id, repeat('x', 1000) || value AS s FROM 
generate_series(1, 20000);
   CREATE TABLE r AS SELECT value AS id, repeat('x', 1000) || value AS s FROM 
generate_series(1, 20000);
   
   -- join on the wide string column
   EXPLAIN ANALYZE SELECT max(l.id), max(r.id), max(l.s), max(r.s) FROM l JOIN 
r ON l.s = r.s;
   -- join on the integer column, same columns kept
   EXPLAIN ANALYZE SELECT max(l.id), max(r.id), max(l.s), max(r.s) FROM l JOIN 
r ON l.id = r.id;
   ```
   
   Observed `SortMergeJoinExec` metrics:
   
   | join key | peak_mem_used |
   |---|---|
   | `l.s = r.s` | 38.8 MB |
   | `l.id = r.id` | 19.7 MB |
   
   ### Expected behavior
   
   Both queries should report about the same `peak_mem_used`, because the 
buffered batches are the same. A key array that is a column of the batch should 
not be charged again.
   
   ### Additional context
   
   A possible fix is to charge only the key arrays that do not share buffers 
with the batch (for example, skip `Column` keys, or count buffers by pointer 
once per batch).
   
   Related: https://github.com/apache/datafusion/issues/16841 and 
https://github.com/apache/datafusion/issues/22758.
   


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