Peter Toth created SPARK-59575:
----------------------------------

             Summary: Storage-partitioned join is lost when a marked layout's 
declared key order is not sorted
                 Key: SPARK-59575
                 URL: https://issues.apache.org/jira/browse/SPARK-59575
             Project: Spark
          Issue Type: Bug
          Components: SQL
    Affects Versions: 5.0.0
            Reporter: Peter Toth


A marked {{KeyedPartitioning}} (one with {{mayContainUnknownPartitionKeys}}, 
produced only by the one-side shuffle behind 
{{spark.sql.sources.v2.bucketing.shuffle.enabled}}) pins the rows whose key it 
does not declare to {{hash(key) % numPartitions}} over the keys it does 
declare, *in the order it declares them*.

{{EnsureRequirements.mergeAndDedupPartitions}} sorts the merged partition key 
list, for the determinism SPARK-41471 asked for. So a marked layout whose 
declared order is not the sorted one is relabelled by the regrouping even where 
the key set is unchanged. That is what a one-side shuffle onto a 
{{UnionExec}}'s key order leaves behind. {{GroupPartitionsExec}} then gives up 
the keyed claim, because only an identity regrouping keeps it, and since 
SPARK-59272 the pairing gate declines and the join shuffles both sides.

This is a regression rather than a missing optimization. The "three shuffles to 
four" plan change SPARK-59272 lists as its user-facing change is exactly this 
shape. Measured: handing the marked side its own key list verbatim takes the 
{{SPARK-59050: SPJ: regrouping a marked layout must not keep the unknown-keyed 
claim}} query back to three shuffles, with a correct answer and a plan 
{{ValidateRequirements}} accepts. So the fourth shuffle was not necessary in 
principle, only given the rest of the machinery.

What blocks the obvious fix: {{KeyedPartitioning.createShuffleSpec}} sorts an 
unmarked side through {{toGrouped}} under 
{{spark.sql.sources.v2.bucketing.allowKeysSubsetOfPartitionKeys.enabled}}, 
while it hands a marked layout back unprojected. With the merged list left in 
the marked side's order, the two children then hold one partitioning but report 
two specs that {{KeyLayout.describesSameKeys}} calls different, so 
{{ValidateRequirements}} rejects the join the gate just allowed. The generated 
sweep added by SPARK-59272 catches it on cell {{left=id/12 right=id/312/marked 
Inner}}. That asymmetry has to be settled first.

One further wrinkle for whoever takes this: the merge runs on *reduced* keys, 
so "the marked side's keys verbatim" means its reduced keys, and the rule needs 
a reducer exception. A reducer forfeits the claim on its own through 
{{keysRewritten}}.

The other half of the same regression, where partition filtering narrows the 
merged list below the marked side's declared keys, is fixed separately by 
SPARK-59272's follow-up (apache/spark#58858). This ticket is only the ordering 
half.




--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to