Skip to content

feat: let SpillCompression::Zstd carry a compression level - #26365

Open
KonaeAkira wants to merge 3 commits into
apache:mainfrom
KonaeAkira:spill-compression-zstd-level
Open

KonaeAkira wants to merge 3 commits into
apache:mainfrom
KonaeAkira:spill-compression-zstd-level

Conversation

@KonaeAkira

@KonaeAkira KonaeAkira commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Rationale for this change

Allows for configuring the zstd compression level for spill files instead of always using arrow's default compression level (3). Possible now that arrow-rs exposes IpcWriteOptions::try_with_compression_level.

What changes are included in this PR?

  • SpillCompression::Zstd becomes SpillCompression::Zstd(u32) with SpillCompression::DEFAULT_ZSTD_LEVEL = 3.
  • datafusion.execution.spill_compression accepts zstd(<level>) with a level in 0..=22, parsed and validated at SET time. Plain zstd means level 3 to preserve current behavior.
  • The compression level is passed onto arrow via IpcWriteOptions::try_with_compression_level.

What is the testing strategy for this PR?

  • 2 new parse tests in datafusion/common/src/config.rs.
  • 1 new test in datafusion/physical-plan/src/spill/mod.rs to assert that setting zstd compression level actually changes compression behavior.
  • sqllogictests in datafusion/sqllogictest/test_files/information_schema.slt.

Are there any user-facing changes?

Yes, breaking change because SpillCompression is a public enum. Added an upgrade guide to docs/source/library-user-guide/upgrading/56.0.0.md.

@github-actions github-actions Bot added documentation Improvements or additions to documentation core Core DataFusion crate sqllogictest SQL Logic Tests (.slt) common Related to common crate physical-plan Changes to the physical-plan crate labels Oct 15, 2026
…l-compression-zstd-level

# Conflicts:
#	docs/source/library-user-guide/upgrading/56.0.0.md
@github-actions github-actions Bot added the auto detected api change Auto detected API change label Oct 15, 2026
@codecov-commenter

codecov-commenter commented Oct 15, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.72848% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.84%. Comparing base (91cd7ff) to head (65bcaeb).
⚠️ Report is 196 commits behind head on main.

Files with missing lines Patch % Lines
datafusion/physical-plan/src/spill/mod.rs 80.43% 1 Missing and 8 partials ⚠️
datafusion/common/src/parquet_config.rs 93.75% 0 Missing and 3 partials ⚠️
datafusion/common/src/config.rs 96.22% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main   #26365   +/-   ##
=======================================
  Coverage   82.84%   82.84%           
=======================================
  Files        1151     1151           
  Lines      455510   455601   +91     
  Branches   455510   455601   +91     
=======================================
+ Hits       377362   377440   +78     
- Misses      55236    55243    +7     
- Partials    22912    22918    +6     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@kosiew

kosiew commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

@KonaeAkira
Can you resolve the merge conflicts?

Brings in 363 upstream commits (through 4bf32cb).

Conflicts resolved:
- datafusion/common/src/config.rs: unioned the parquet_config import
  lists from both sides.
- docs/source/library-user-guide/upgrading/56.0.0.md: both sides appended
  a section ending in a migration-guide code block, which interleaved.
  Kept upstream's sections in place and moved the SpillCompression::Zstd
  section, with its own migration block, to the end.
- docs/source/user-guide/configs.md: regenerated via
  dev/update_config_docs.sh.

Upstream also added spill tests that construct the now-tupled Zstd
variant, so SpillCompression::Zstd became
SpillCompression::Zstd(SpillCompression::DEFAULT_ZSTD_LEVEL) in
datafusion/physical-plan/src/spill/lengths.rs (new upstream file, 3
sites) and in one rstest case in spill/mod.rs.
@KonaeAkira

Copy link
Copy Markdown
Contributor Author

@kosiew Done. Sorry it's been a while :)

@github-actions github-actions Bot removed the auto detected api change Auto detected API change label Nov 7, 2026

@kosiew kosiew left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KonaeAkira,

Thanks for adding configurable Zstd compression levels for spill files. This addresses a useful performance-tuning limitation while preserving the existing default behavior. The implementation is appropriately scoped, and the new tests demonstrate that non-default levels produce readable spill files.

The design keeps compression policy in the existing configuration model and delegates encoding to Arrow IPC. Carrying the level in SpillCompression is a reasonable extension, and reusing the Parquet parsing helpers avoids duplicating validation logic. The intentional Rust API change is documented with migration guidance.

I found no blocking issues. I've left two optional suggestions to strengthen boundary and decoded-value coverage.

"zstd(3)",
),
("ZSTD(1)", SpillCompression::Zstd(1), "zstd(1)"),
("zstd(22)", SpillCompression::Zstd(22), "zstd(22)"),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding ("zstd(0)", SpillCompression::Zstd(0), "zstd(0)") to the round-trip cases. Zero is the documented lower boundary and default-level alias, so this would verify that parsing and display preserve the explicit zero setting.

"level {level}"
);
validate(&spill_manager, file, num_rows, Arc::clone(&schema), 1).await?;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider collecting the decoded stream and comparing its batches with batches, while retaining the existing metrics and schema checks. The current validate helper checks row metrics, schema, and batch count but not decoded values, so this would strengthen round-trip coverage for levels 1 and 19.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

common Related to common crate core Core DataFusion crate documentation Improvements or additions to documentation physical-plan Changes to the physical-plan crate sqllogictest SQL Logic Tests (.slt)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants