Skip to content

Make insert_broadcast_execs idempotent for existing broadcast inputs #675

Description

@sesteves

Problem

insert_broadcast_execs always inserts a new BroadcastExec beneath an eligible join, even when the build input already has the canonical broadcast shape:

CoalescePartitionsExec
  BroadcastExec
    input

For a fetch-less CoalescePartitionsExec, the pass unwraps the coalesce and uses its input as the payload for a new broadcast. If that input is already a BroadcastExec, the resulting plan becomes:

CoalescePartitionsExec
  BroadcastExec
    BroadcastExec
      input

Applying the pass repeatedly adds another broadcast layer each time.

Impact

The nested broadcasts preserve query results, but they create unnecessary cache state and duplicate memory reservations for the same batches. This increases memory pressure and can make spilling or resource-exhaustion failures more likely.

It also means the optimizer pass is not idempotent, which is surprising when plans have already been processed or when an earlier custom optimizer has inserted the canonical broadcast shape.

Proposed behavior

Before inserting a broadcast, inspect the build input:

  • If it is already CoalescePartitionsExec(BroadcastExec(...)) with no fetch, leave it unchanged.
  • If the build is directly a BroadcastExec, add only the required coalesce wrapper rather than another broadcast layer, if that shape is supported.
  • Preserve the existing handling for fetch-bearing CoalescePartitionsExec, where the fetch must remain below the broadcast.

The exact normalization can vary, but a second application of insert_broadcast_execs should produce the same plan as the first.

Testing

Add focused tests for:

  • HashJoinExec with an existing canonical broadcast build.
  • NestedLoopJoinExec with an existing canonical broadcast build.
  • CrossJoinExec with an existing canonical broadcast build.
  • A direct BroadcastExec build input, if supported.
  • A fetch-bearing coalesce to ensure its limit remains below the broadcast.
  • Applying insert_broadcast_execs twice and asserting that the second result is structurally unchanged.

Plan assertions should verify that every eligible build contains exactly one BroadcastExec layer.

Acceptance criteria

  • Existing canonical broadcast build inputs are not wrapped again.
  • Repeated optimizer application is idempotent.
  • HashJoin, NestedLoopJoin, and CrossJoin are covered.
  • Fetch-bearing coalesce semantics are preserved.
  • Existing broadcast planning and correctness tests continue to pass.

References

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions