Use ZSTD as the default compression codec for Parquet files #19615
Replies: 5 comments 8 replies
|
As long as its stable - we can switch.. Have others switched? We hit the same memory leak and rolled back. But, with higher spark /parquet version - it seems to work well. |
|
Can we do it such that zstd is default, but for lower/problematic spark versions - we override |
|
+1 to this proposal. Switching native Parquet log files from GZIP to ZSTD makes complete sense for MOR workloads. Since log files are intermediate representations that undergo frequent write and compaction cycles, prioritizing compression throughput and CPU efficiency without a significant penalty on compression ratio is a huge win for MOR write latency. A few thoughts on the implementation & safeguard details:
Thanks for putting together a detailed proposal! |
|
On "have others switched?" - Delta and Spark default to snappy, Iceberg and Paimon to zstd; nobody stayed on gzip. Iceberg's switch is worth a look though: since 1.4.0 the zstd default is only stamped into the properties of newly created tables, so existing tables keep writing gzip on a library upgrade (iceberg#15236). So one thing to decide explicitly: does the new default apply to every table on the next commit after a jar upgrade, or only to new ones? Hudi persists nothing about the codec in On overriding to On scope: Two smaller notes: |
+1. we can do it in the next major version release.
sg. but zstd is as light as snappy, anyway? |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Summary
Hudi MOR tables now use native Parquet log files by default, regardless of whether the LSM file-group layout is enabled.
Native log files currently use GZIP compression by default. GZIP provides a good compression ratio, but its relatively low compression throughput adds considerable CPU overhead to the MOR write path.
This discussion proposes using ZSTD as the default compression codec for native Parquet log files.
Motivation
For MOR tables, updates are first written to native log files. Readers merge base files and log files, and compaction eventually rewrites the file slice into a new base file.
Native log files are therefore intermediate files in the MOR write lifecycle. Compression throughput and CPU efficiency are particularly important because the data will later be rewritten during compaction.
The main codec choices are:
ZSTD appears to provide a better balance between write throughput, storage size, and read I/O (Benchmark)
Related Hudi discussions include:
Adoption in other table formats
Apache Iceberg changed the default Parquet compression codec for new tables from GZIP to ZSTD in Iceberg 1.4.0. Existing tables retained their previous behavior to minimize compatibility impact (Iceberg PR #8593).
Delta Lake has adopted ZSTD as the protocol-level default. However, its Spark implementation is still transitioning and has not yet fully switched from SNAPPY to ZSTD.
Known ZSTD off-heap memory issue
Older parquet-java versions have a known ZSTD off-heap memory issue:
The old Parquet decompression path did not explicitly close
ZstdDecompressorStream. Because the stream holds native resources allocated throughzstd-jni, long-running jobs could experience off-heap memory growth or fragmentation and eventually run out of memory.The issue was fixed in parquet-java 1.13.0.
Spark also introduced a workaround in SPARK-41952, released in Spark 3.2.4, 3.3.3, and 3.4.0.
However, the Spark workaround only covers the vectorized Parquet reader. Hudi's file-group reader uses the non-vectorized reader for row-based record merging, so profiles using parquet-java 1.12.x may still be affected.
This is currently relevant to the Spark 3.3 and Spark 3.4 Hudi profiles.
Proposal
Change the default compression codec for native Parquet log files from GZIP to ZSTD.
For dependency profiles using parquet-java 1.12.x, Hudi should add a scoped workaround equivalent to PARQUET-2160 in its non-vectorized file-group read path.
Profiles using parquet-java 1.13.0 or newer should continue using the upstream implementation.
The workaround would only protect Hudi's own file-group reader. It would not attempt to modify arbitrary non-vectorized Parquet reads outside Hudi.
Runtime dependency
Parquet's
ZstandardCodecdepends onzstd-jni.Before making ZSTD the default, Hudi should verify that supported runtime environments provide a compatible
zstd-jnidependency.Where the runtime does not guarantee this dependency, the corresponding Hudi bundle should package it explicitly.
All reactions