Skip to content

fix: keep aggregates above undecided joins partial and final - #2806

Merged
andygrove merged 1 commit into
apache:mainfrom
andygrove:fix/undecided-join-partitioning
Nov 8, 2026
Merged

andygrove merged 1 commit into
apache:mainfrom
andygrove:fix/undecided-join-partitioning

Conversation

@andygrove

Copy link
Copy Markdown
Member

Which issue does this PR close?

No issue. Split out of #2792.

Rationale for this change

Until AQE decides an undecided join (DynamicJoinSelectionExec), the join reports the output partitioning of the join it was planned as. A CollectLeft hash join passes its right input's partitioning through. So a join that was planned with a one-partition table on the right, such as nation, reports one output partition, even though the join it resolves into may build that small table and output the other side's partitions.

DataFusion's CombinePartialFinalAggregate runs during each replan. It sees an aggregate over what claims to be one partition and merges the Partial and Final pair into a single Single aggregate, which later replans cannot split back apart. Once the join resolves, the aggregate's input is coalesced and exchanged below it, and every task of the consuming stage reads and aggregates the whole input.

In TPC-H q11 this hits the scalar sum subquery. At SF1000 with 256 partitions, each of 16 tasks read all 32M input rows, and the query took 14.7 s. With this change it takes 5.4 s (Spark + Comet on the same cluster: 43.7 s). The behavior is on main today.

What changes are included in this PR?

  • DynamicJoinSelectionExec reports UnknownPartitioning with the larger of its inputs' partition counts when the planned join reports fewer, both when it is built (from_hash_join, from_sort_join) and in with_new_children. Partial and final aggregates above it therefore stay split. Once the join is decided, the real join's properties take over.
  • Test undecided_join_reports_at_least_its_widest_input: a CollectLeft join with a one-partition right input must report the wider left input's partition count, including after replace_children.

Are there any user-facing changes?

No. Only plans with an aggregate above an undecided join over a one-partition input change: the aggregate stays partial and final instead of becoming single.

An undecided AQE join (DynamicJoinSelectionExec) reported the
partitioning of the join it was planned as. A CollectLeft join passes
its right input's partitioning through, so a join planned with a
one-partition table such as nation on the right reported one partition,
although the join it resolves into may build nation and output the
other side's partitions. Meanwhile DataFusion's CombinePartialFinal-
Aggregate saw an aggregate over one partition and merged it into a
Single aggregate, which later replans cannot split. Once the join
resolved, the aggregate's input was coalesced and exchanged below it,
so every task of the consuming stage read and aggregated the whole
input: TPC-H q11's scalar sum read all 32M rows in each of 16 tasks at
SF1000 with 256 partitions.

Report at least as many partitions as the widest input until the join
is decided.

@milenkovicm milenkovicm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @andygrove

@andygrove
andygrove added this pull request to the merge queue Nov 8, 2026
Merged via the queue into apache:main with commit 76584d0 Nov 8, 2026
36 of 37 checks passed
@andygrove
andygrove deleted the fix/undecided-join-partitioning branch November 8, 2026 10:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants