SortMergeJoinExec double counts join key columns in the buffered batch reservation

オープン
#27,322 コメント 3 件 リアクション 0 件 担当者 1 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

@Kristofferjoha がすでに取り組んでいます。

2026年11月11日 から。

  • #27346 @Kristofferjoha による — オープン

評価

この issue はまだ評価されていません。

説明

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

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.

主要言語
Rust
スター
9.6k
フォーク
2.6k
平均マージ
3日 4時間
マージ済み PR(30日)
345

環境構築

Codespaces で開く

このプロジェクトの開発コンテナを、あなたの GitHub アカウントでブラウザ上に起動します。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

apache/datafusion のほかの issue

apache/datafusion の issue をすべて見る

似ている issue

Rust の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。