[core] Split large normal files in data evolution compaction - #9709
Merged
JingsongLi merged 5 commits intoSep 10, 2026
Merged
Conversation
JingsongLi
force-pushed
the
codex/data-evolution-split-large-files
branch
from
September 10, 2026 05:15
57186a4 to
4d4d207
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
Allow Data Evolution tables to resize oversized historical normal files after lowering
target-file-size, while preserving the rule that every dedicated BLOB/VECTOR file is fully contained in one normal file's row-ID range.Add
data-evolution.compaction.split-large-files(default:false) anddata-evolution.compaction.large-file-ratio(default:2.0, finite and at least1.0). An individual normal file strictly exceeding the configured ratio timestarget-file-sizemay trigger compaction belowcompaction.min.file-num. Combined version sizes alone do not bypass the minimum file count.Before writing, estimate rows per output from the total normal input file size and logical row count, then move cuts inside dedicated files to the ends of their overlapping ranges. Protect ranges across columns and historical versions, plus ranges produced by dedicated compaction in the same batch. Each normal task uses the existing direct writer with automatic size/row rolling disabled and explicitly finishes one file per planned range. Output sizes are approximate and can differ from the target due to compression, data skew, overwritten versions, or dedicated boundaries.
Skip size-only tasks when dedicated ranges prevent any split; ordinary small-file and column-version merging remains available. Dedicated files retain their contents and names unless their separate compaction option requests rewriting them. Preserve row IDs, column sequence metadata, and logical deletions, redistributing deletion vectors to the new normal anchors.
Carry protected ranges in the transient compaction task serializer (version 4; older in-flight/savepoint jobs must restart). Within one Spark COMPACT invocation, bins containing only successfully written normal outputs do not trigger repeated normal rewrites. Include successful conflict-retry outputs; a later COMPACT invocation can select these historical files again.
Validation
Regression coverage includes configurable ratio boundaries, mixed splitting and merging, estimated output ranges, nonzero and extreme row IDs, input-size overflow, cross-column and historical dedicated overlaps, full-range VECTOR protection, same-batch BLOB compaction, task serialization, dedicated-file identity and containment, row and projected reads, column sequence metadata, and deletion vectors. Parquet coverage verifies that its uncompressed write buffer cannot change the planned file boundaries. Buffered-write and write-time row-limit settings cannot cut through a protected range.
Broader validation before the base update passed 481 Java regression cases (457 core and 24 common). On master
06d0653f68, all 84 focused core cases passed again: 45 coordinator/planning, 13 normal-task, and 26 deletion-vector cases.Both focused Spark 3.5 regressions also passed on the updated base: oversized outputs constrained by dedicated ranges are processed once per COMPACT invocation across candidate batches, and the commit observer receives the successful rebased outputs after a same-boundary partial update. Repeating COMPACT starts a new invocation and can process the historical files again.
Checkstyle, Spotless, and Maven Enforcer passed without
fast-build. Local Java validation uses JDK 17 with the existing Byte Buddy agent preloaded andnet.bytebuddy.experimental=truefor the repository's Mockito version.The full Spark suite is not claimed as passing: a previous test-lifecycle run hit a
ParquetFileReader.openlinkage failure because the unshaded reactorpaimon-formatclass shadows Spark's Parquet class. Native Lance and Flink runtime suites were not run locally.