[SPARK-58102][SQL] Fix SLAM scope extraction bailing out on ReusedSubqueryExec#57226
Open
juliuszsompolski wants to merge 1 commit into
Open
[SPARK-58102][SQL] Fix SLAM scope extraction bailing out on ReusedSubqueryExec#57226juliuszsompolski wants to merge 1 commit into
juliuszsompolski wants to merge 1 commit into
Conversation
…queryExec `SQLLastAttemptAccumulator.extractStageRDDScopes` walks `executedPlan` to find the RDD scopes belonging to a Dataset's execution. Its `BaseSubqueryExec` match enumerates `SubqueryExec`, `SubqueryBroadcastExec`, `SubqueryAdaptiveBroadcastExec` and then bails on the catch-all, setting `bailOutReason`. `ReusedSubqueryExec` was not handled, so any plan containing a reused subquery (subquery reuse is on by default via `spark.sql.execution.reuseSubquery`) hit the catch-all and made `lastAttemptValueForDataset` / `lastAttemptValueForQueryExecution` return None. Handle `ReusedSubqueryExec` by recursing into its `child`, mirroring the existing `ReusedExchangeExec` case. `ReusedSubqueryExec` is a `LeafExecNode` whose `child` is a field (not a plan child), so the normal traversal never reaches it. Recursing collects the reused subquery's scopes; if the original `SubqueryExec` is still present elsewhere in the tree those scopes are collected twice, but that is harmless because `lastAttemptValueForRDDScopes` deduplicates by scope. Add a `SQLLastAttemptMetricPlanShapesSuite` test whose plan produces a `ReusedSubqueryExec` (a nested `range(5)` subquery pushed into the scan DataFilters and duplicated). Before the fix it returned None; after it returns the expected value.
Contributor
Author
|
cc @cloud-fan , I would consider branch-4.2 as well, since it's a small fix to a new feature that was newly added in 4.2 |
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?
SQLLastAttemptAccumulator.extractStageRDDScopeswalks a Dataset'sexecutedPlanto find theRDDOperationScopeids of the stages that make up its execution, so thatSQLLastAttemptAccumulatorcan attribute "last attempt" metric updates to that execution. Its
BaseSubqueryExecmatch handlesSubqueryExec,SubqueryBroadcastExecandSubqueryAdaptiveBroadcastExec, and then bails out on acatch-all
case p =>that records abailOutReason. When extraction bails out,lastAttemptValueForQueryExecution/lastAttemptValueForDatasetreturnNone.ReusedSubqueryExecwas not enumerated, so any plan containing a reused subquery hit the catch-alland caused
lastAttemptValueForDataset/lastAttemptValueForQueryExecutionto returnNone.Subquery reuse is enabled by default (
spark.sql.execution.reuseSubquery), and aReusedSubqueryExecis produced whenever the same subquery appears more than once in a plan --including when predicate pushdown duplicates a subquery into a scan's data filters.
This PR adds a
ReusedSubqueryExeccase that recurses into itschild, mirroring the existingReusedExchangeExechandling.ReusedSubqueryExecis aLeafExecNodewhosechildis a fieldrather than a plan child, so the normal plan traversal never descends into it; recursing collects
the reused subquery's scopes. If the original
SubqueryExecis still present elsewhere in the plan,its scopes are collected twice, but that is harmless:
lastAttemptValueForRDDScopesdeduplicates byscope (it reduces the collected scope ids to a set and aggregates one RDD per scope).
Why are the changes needed?
Without this,
lastAttemptValueForDataset/lastAttemptValueForQueryExecutionsilently returnNonefor any query whose physical plan contains aReusedSubqueryExec, even though the metric wastracked correctly. Because subquery reuse is on by default, this affects common queries -- e.g. the
same scalar/
INsubquery referenced twice, or a subquery duplicated into aFileScan's data filtersby predicate pushdown.
Does this PR introduce any user-facing change?
No.
How was this patch tested?
Added a test to
SQLLastAttemptMetricPlanShapesSuitewhose physical plan contains aReusedSubqueryExec: a scalar subquery with a nested(SELECT MIN(id) FROM range(5))predicate thatgets pushed into the outer subquery's scan data filters and duplicated, so subquery reuse rewrites one
copy to a
ReusedSubqueryExec. The test asserts both the metric value and (viatestPhysicalPlanShape) that aReusedSubqueryExecis actually present in the plan -- with afallback for the forced-AQE-replan variants, which bypass subquery reuse and keep the duplicated
subquery as two separate
SubqueryExecnodes (this mirrors the existingexchange - Shuffletest'sReusedExchangeExecfallback). Before the fix,lastAttemptValueForDatasetreturnedNonefor thisplan (assertion
None did not equal Some(300)); after the fix it returns the expected value. Thetest runs across the suite's existing
useAQExfailureModexaqeReplansmatrix (9 variants).Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Opus 4.8)