Repository navigation
[AURON #2579] Fix zero-column round-robin shuffle presort - #2580
Conversation
COUNT(*) above an unkeyed REPARTITION can leave zero-column batches with positive row counts. Presorting them with an empty key list causes division by zero in ExternalSorter. Skip the default ascending presort when no keys are present. This helper has no limit or offset, so the input rows and repartitioning are preserved. Add regression coverage for zero-column batches, empty input and sorting with and without keys.
|
Runtime validation has now been completed on Spark 3.5.9 with Celeborn (RSS), using a rebuilt Auron 9.0.0-SNAPSHOT JAR with this fix backported. |
Backport commit 2057c35 (apache#2580) to v8.0.0. Construct test input directly because the master test helper is unavailable in this release.
lyne7-sc
left a comment
There was a problem hiding this comment.
The fix makes sense to me. could we also add the reproduction sql as a Spark regression test?
Thanks for the review and the suggestion! I’ve added the SQL reproduction as a Spark regression test and verified that it passes with Spark 3.5.9 and Scala 2.12 using: ./build/mvn Could you please take another look when you have a chance? |
slfan1989
left a comment
There was a problem hiding this comment.
LGTM.
The fix preserves zero-column row counts, and the regression tests cover the failure case. Please update the PR description to reflect the completed SQL validation.
Thank you for the feedback. I have updated the PR description accordingly. Could you please review it again and let me know if it does not follow the project’s conventions. |
|
@squanch-c Thanks for the contribution! @lyne7-sc Thanks for the review! |
Which issue does this PR close?
Closes #2579
Rationale for this change
COUNT(*)above an unkeyedREPARTITIONcan leave zero-column input batcheswith positive row counts. Native round-robin presort then passes no columns
to
RowConverter, which produces zero key rows and causes division by zeroin
ExternalSorter.Minimal reproduction with Auron native shuffle conversion enabled:
Expected result:
4, as returned by the JVM engine and by the same querywithout the
REPARTITIONhint. The original Native execution fails with:The captured failing plan includes
Project (Output: [])followed byNativeShuffleExchange (Input: [], RoundRobinPartitioning(2)). This examplereproduced the failure on Spark 3.5.9 using the RSS path. SQL execution with
a rebuilt patched JAR has now been successfully validated on Spark 3.5.9
with Celeborn (RSS).
An empty-key guard existed in the former sorter implementation in #958 and
was removed with that implementation in #1078. This restores the behavior
in the shared presort helper, which has no limit or offset.
What changes are included in this PR?
create_default_ascending_sort_execwhen no sort keysare present. Both local and RSS round-robin shuffle use this helper.
partitions, empty input, and values with and without sort keys.
Are there any user-facing changes?
COUNT(*)over native round-robin repartitioning no longer fails when columnpruning leaves zero input columns. No configuration change is required.
How was this patch tested?
On macOS arm64 with nightly-2025-05-09, upstream vendor setup and unchanged
Cargo.lock:Rust workspace formatting also passed:
Pinned rustfmt and
git diff --checkpassed. An earlier negative-control runof the zero-column regression test reproduced division by zero with only the
helper guard removed.
Runtime SQL validation passed on Spark 3.5.9 with Celeborn (RSS), using a
rebuilt Auron 9.0.0-SNAPSHOT JAR with this fix backported. The previously
failing zero-column round-robin SQL now completes successfully.
The SQL reproduction was also added as the
AURON-2579regression test inAuronDataFrameSuiteand passed with Spark 3.5.9 and Scala 2.12 using:./build/mvn \ -Ppre,spark-3.5,scala-2.12,spark-tests \ -DsparkVersion=3.5.9 \ -pl auron-spark-tests/spark35 \ test -DskipTests=false \ -Dsuites=org.apache.spark.sql.AuronDataFrameSuite \ -Dtests=AURON-2579The test verifies a local native shuffle with zero input columns and
RoundRobinPartitioning(2), and checks thatCOUNT(*)returns4.Was this patch authored or co-authored using generative AI tooling?
Generated-by: OpenAI Codex (GPT-6; exact client build unavailable)