[SPARK-58093][SQL] Push down LIMIT through UNION ALL to Data Source V2 scan#57200
Open
j1wonpark wants to merge 1 commit into
Open
[SPARK-58093][SQL] Push down LIMIT through UNION ALL to Data Source V2 scan#57200j1wonpark wants to merge 1 commit into
j1wonpark wants to merge 1 commit into
Conversation
…2 scan `V2ScanRelationPushDown.pushDownLimit` only handled a scan directly under the limit (optionally through `Project`/`Sort`), so a `LIMIT` on top of a `UNION ALL` fell through to `case other` and was never delivered to the underlying Data Source V2 scans via `SupportsPushDownLimit`. `LimitPushDown` already pushes a `LocalLimit` into each union branch, so the operator-level limit reaches the branches while the source-level limit hint does not. Add `Union` and `LocalLimit` cases to `pushDownLimit` that recurse into each branch and push the limit as a partial limit, always keeping the outer limit operators. UNION ALL never de-duplicates rows, so the union of branches each capped at `limit` still contains the first `limit` rows of the whole union. Signed-off-by: Jiwon Park <jpark92@outlook.kr>
d2b65ba to
c9e8a97
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changes were proposed in this pull request?
V2ScanRelationPushDown.pushDownLimithad no case forUnion, so aLIMITon top of aUNION ALLwas never pushed to the underlying Data Source V2 scans throughSupportsPushDownLimit; it fell through tocase other => (other, false).Note the plan shape:
LimitPushDownalready pushes aLocalLimitinto eachUnionbranch (operator level), but the source-level limit hint (pushDownLimit) stops at theUnion.This PR adds two cases to
pushDownLimit:case u: Union— recurse into each branch, pushing the limit as a partial limit so the limit operators above the union are kept.case l @ LocalLimit(IntegerLiteral(_), _)— look through the per-branchLocalLimitthatLimitPushDowninserts, so the limit reaches the scan.Results are unchanged.
UNION ALLdoes not de-duplicate rows, so the union of branches that each keep at mostlimitrows still contains the firstlimitrows of the whole union — the same reason the existingUnioncase inLimitPushDownis safe. The union may return more thanlimitrows, so the push is only partial and the limit operators stay in the plan.Two things worth calling out for review:
Sort(theSortcase already returns a plan without it). This is fine becauseUniondoes not attach meaning to the order in which it emits its children, and the limit above the union still caps the result.LIMITover anORDER BYthat sits above the union is not pushed at all, which a test covers.Unioncase always reports the limit as not removable, plans that combineLIMITwithOFFSETcan callpushLimiton the same builder twice with the same value. This already happens today for partially pushed scans and is idempotent for the sources in the repository.Why are the changes needed?
SELECT ... FROM a UNION ALL SELECT ... FROM b LIMIT nnever delivers theLIMITto the scans, so each source does more work than necessary. Any Data Source V2 connector implementingSupportsPushDownLimitbenefits from receiving the limit per branch — e.g. for JDBC, each branch's pushed-down SQL then carriesLIMIT n.Does this PR introduce any user-facing change?
No. Query results are identical. The only observable difference is that the pushed limit now appears on each
UNION ALLbranch's scan (e.g.PushedLimit: LIMIT nin the plan, or aLIMITclause in the JDBC SQL), reducing work at the source.How was this patch tested?
Added five tests to
JDBCV2Suite, each asserting the limit pushed to every branch scan:checkAnswer;Sortis dropped;OFFSET, covering bothLIMIT n OFFSET m(branches keepn + mrows) andlimit(n).offset(m)(branches keepnrows);LIMITover anORDER BYon top of the union is not pushed to the scans.Ran the full
JDBCV2Suite(86 tests) — no regression.Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Claude Opus)