Skip to content

feat(storage): support separate zstd level for native parquet logs - #19781

Open
cshuo wants to merge 3 commits into
apache:masterfrom
cshuo:support_native_log_zstd_level
Open

feat(storage): support separate zstd level for native parquet logs#19781
cshuo wants to merge 3 commits into
apache:masterfrom
cshuo:support_native_log_zstd_level

Conversation

@cshuo

@cshuo cshuo commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

Describe the issue this Pull Request addresses

Closes #19780.

The global Hadoop parquet.compression.codec.zstd.level setting currently applies to both Parquet base files and native Parquet log files. Native logs favor write latency and may not need the higher compression level selected for base files, but there is no independent native-log setting.

Summary and Changelog

  • Add the advanced hoodie.logfile.parquet.compression.codec.zstd.level configuration with a default value of 1.
  • Add a ParquetUtils helper that applies the native-log level only to native log paths, copying the storage configuration only when the global level is absent or different.
  • Apply the built-in native-log override before HoodieParquetConfigInjector in Spark, Flink, and Avro/Java Parquet writer factories, preserving the custom injector as the highest-priority extension point.
  • Add unit coverage for the default level, explicit override, equal-level configuration reuse, missing global configuration, and unaffected base-file paths.

Impact

Users can tune native Parquet log Zstd compression independently from base files. Native logs default to level 1, while base files retain the global Hadoop setting. This adds one optional advanced configuration and does not change Hudi's storage format or public APIs.

Risk Level

Low. The override is limited to native log paths, base-file paths retain the original configuration instance, and custom Parquet config injectors still run last. The targeted TestParquetUtils#testApplyNativeLogZstdCompressionLevel and Flink Parquet writer factory test passed.

Documentation Update

The new configuration and its default behavior are documented in HoodieStorageConfig. No storage-format documentation changes are required.

Contributor's checklist

  • Read through contributor's guide
  • Enough context is provided in the sections above
  • Adequate tests were added if applicable
@codecov-commenter

codecov-commenter commented Aug 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.87500% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 78.31%. Comparing base (efe02e1) to head (0d0fe35).
⚠️ Report is 18 commits behind head on master.

Files with missing lines Patch % Lines
...apache/hudi/common/config/HoodieStorageConfig.java 83.33% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master   #19781      +/-   ##
============================================
+ Coverage     78.11%   78.31%   +0.19%     
- Complexity    33673    33894     +221     
============================================
  Files          2540     2541       +1     
  Lines        141413   141759     +346     
  Branches      17123    17351     +228     
============================================
+ Hits         110467   111019     +552     
+ Misses        23250    23036     -214     
- Partials       7696     7704       +8     
Components Coverage Δ
hudi-common 83.64% <83.33%> (+0.07%) ⬆️
hudi-client 83.21% <100.00%> (+0.09%) ⬆️
hudi-flink 85.68% <100.00%> (+0.01%) ⬆️
hudi-spark-datasource 73.21% <ø> (+0.67%) ⬆️
hudi-utilities 74.55% <ø> (+0.05%) ⬆️
hudi-cli 15.06% <ø> (ø)
hudi-hadoop 70.78% <100.00%> (+0.68%) ⬆️
hudi-sync 75.56% <ø> (-0.08%) ⬇️
hudi-io 79.88% <ø> (+0.12%) ⬆️
hudi-timeline-service 83.44% <ø> (ø)
hudi-cloud 65.81% <ø> (ø)
hudi-kafka-connect 53.20% <ø> (ø)
Flag Coverage Δ
common-and-other-modules 51.45% <65.62%> (-0.03%) ⬇️
flink-integration-tests 48.83% <70.00%> (-0.03%) ⬇️
hadoop-mr-java-client 44.07% <67.85%> (+0.06%) ⬆️
integration-tests 13.52% <59.37%> (-0.01%) ⬇️
spark-client-hadoop-common 50.56% <90.00%> (+0.18%) ⬆️
spark-java-tests 52.21% <70.00%> (+0.08%) ⬆️
spark-scala-tests 46.95% <70.00%> (+0.21%) ⬆️
utilities 36.56% <70.00%> (+0.27%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...io/storage/row/HoodieRowDataFileWriterFactory.java 97.22% <100.00%> (+0.07%) ⬆️
.../hudi/io/storage/HoodieSparkFileWriterFactory.java 79.77% <100.00%> (+0.22%) ⬆️
...java/org/apache/hudi/common/util/ParquetUtils.java 92.20% <100.00%> (+0.78%) ⬆️
...io/storage/hadoop/HoodieAvroFileWriterFactory.java 91.42% <100.00%> (+0.12%) ⬆️
...apache/hudi/common/config/HoodieStorageConfig.java 89.91% <83.33%> (+0.19%) ⬆️

... and 73 files with indirect coverage changes

🚀 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.
@github-actions github-actions Bot added the size:M PR with lines of changes in (100, 300] label Aug 28, 2026

@hudi-agent hudi-agent 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.

⚠️ 🤖 This review was generated by an AI agent and may contain mistakes. Please verify any suggestions before applying.

Thanks for working on this! This PR adds a hoodie.logfile.parquet.compression.codec.zstd.level config (default 1) and a ParquetUtils helper that applies it only to native Parquet log paths, wired into the Spark/Flink/Avro writer factories ahead of the custom injector. The mechanics look correct — newInstance() deep-copies so base-file configs aren't mutated, and native-vs-base path detection is right. One thing worth double-checking is the backward-compat implication of the default value, noted inline. Please take a look at any inline comments, and this should be ready for a Hudi committer or PMC member to take it from here. One naming nit worth addressing; code is otherwise clean and well-structured.

Comment thread hudi-common/src/main/java/org/apache/hudi/common/config/HoodieStorageConfig.java Outdated
return storageConf;
}

int nativeLogZstdLevel =

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.

Two small robustness improvements here: can we use Parquet's ZstandardCodec.PARQUET_COMPRESS_ZSTD_LEVEL constant instead of duplicating the key (or document why an older-Parquet compatibility constraint requires the literal), and compare the existing value with the desired value as strings instead of calling Integer.parseInt? A malformed inherited global value should be replaceable by an explicit native-log override rather than failing before the override is applied.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 47c2d95. The code now uses ZstandardCodec.PARQUET_COMPRESS_ZSTD_LEVEL. We intentionally retain fail-fast validation for an explicitly malformed global value, with a clear HoodieException and dedicated test, rather than silently hiding user misconfiguration.

Addresses review comments 3901121902, 3910843797, 3910843801, and 3910843806.

@cshuo cshuo left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed all current review feedback in 47c2d95.

@hudi-agent hudi-agent 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.

⚠️ 🤖 This review was generated by an AI agent and may contain mistakes. Please verify any suggestions before applying.

Thanks for working on this! The PR adds an advanced hoodie.logfile.parquet.compression.codec.zstd.level config (default 1) and a ParquetUtils helper that applies it only to native .log.parquet write paths, ahead of the custom config injector, across the Spark, Flink, and Avro/Java writer factories. I traced the native-log write path (HoodieNativeLogFormatWriterHoodieFileWriterFactory.getFileWriter → the path-based newParquetFileWriter), confirmed newInstance() deep-copies so the shared/base-file config is never mutated, and confirmed the level change is compression-ratio-only with no storage-format or read-compat impact. No new issues flagged from this automated pass beyond the backward-compat default and codec-applicability points already raised in earlier rounds. A Hudi committer or PMC member can take it from here for a final review.

* Prepares the storage and Hudi configurations used by a Parquet writer. Built-in writer configuration
* overrides are applied first so that the user-provided config injector remains the highest-priority extension point.
*/
public static Pair<StorageConfiguration, HoodieConfig> prepareParquetWriterConfigs(

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.

-> ingectParquetWriterConfigs

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 0d0fe35. Renamed the helper to injectParquetWriterConfigs and updated all Spark, Flink, Avro, and test call sites.

* The input configuration is copied only when its ZSTD level is absent or differs from the native log level,
* so base file writers and other users of the shared configuration are not affected.
*/
public static <T> StorageConfiguration<T> applyNativeLogZstdCompressionLevel(

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.

-> ingectDefaultZstdCompressionLevel

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 0d0fe35. Renamed the helper to injectDefaultZstdCompressionLevel and updated the related tests and documentation.

Addresses review comments 3912563203 and 3912569450.

@cshuo cshuo left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed the two rename comments in 0d0fe35. The helpers are now named injectParquetWriterConfigs and injectDefaultZstdCompressionLevel, with all production and test references updated.

@hudi-bot

hudi-bot commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

CI report:

Bot commands @hudi-bot supports the following commands:
  • @hudi-bot run azure re-run the last Azure build
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M PR with lines of changes in (100, 300]

5 participants