You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
perf: collapse chained projections in a single optimizer pass; reduce memory usage / recursion (apache#22389)
## Which issue does this PR close?
- Closesapache#22391.
## Rationale for this change
Long chains of consecutive projections (e.g. `SELECT *, <expr> AS dN
FROM ...` stacked N times, with depth-K nested CASE per step) caused
planning to use multi-GB of RAM and tens of seconds of wall time,
scaling superlinearly in chain length and CASE depth. See apache#22391 for the
OOM/timing data.
## What changes are included in this PR?
Three independent fixes targeting the same workload:
1. **Physical chain collapse**
(`datafusion/physical-plan/src/projection.rs`): replace the pairwise
recursive unification in `ProjectionExec::try_swapping_with_projection`
with `try_collapse_projection_chain`, which walks the entire run of
consecutive `ProjectionExec`s and builds **one** final `ProjectionExec`
(saves N-1 intermediate constructions and their `compute_properties`
calls). Leaf pushdown into a non-`Projection` input is preserved by
calling `remove_unnecessary_projections` once at the end.
2. **Logical iterative merge**
(`datafusion/optimizer/src/optimize_projections/mod.rs`): wrap
`merge_consecutive_projections` in an internal loop so an N-deep
`LogicalPlan::Projection` chain collapses in a single rule application
instead of N outer fixpoint passes.
3. **`update_expr` Column-equality short-circuit**
(`datafusion/physical-expr/src/projection.rs`): when substituting a
Column with one that equals it (the pass-through case during chain
collapse), return `Transformed::no` so `transform_up` does not rebuild
the enclosing `CaseExpr` / `CaseBody`. This is the OOM fix — it
eliminates the O(N² · K²) cascade of CASE allocations.
## Are these changes tested?
- yes, existing test + added bench
| Stage | Time | Δ vs master |
|---|---:|---:|
| master | 623 ms | — |
| + chain collapse + logical merge loop | 364 ms | −41.5% |
| + `update_expr` Column-equality short-circuit | **155 ms** |
**−75.4%** |
(criterion p<0.05, CI [−75.67%, −75.16%])
## Are there any user-facing changes?
No public API change.
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 commit comments