-
Notifications
You must be signed in to change notification settings - Fork 2.5k
fix(flink): fix the mor small file record size estimation #18991
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -117,7 +117,6 @@ public WriteProfile(HoodieWriteConfig config, HoodieFlinkEngineContext context) | |
| this.context = context; | ||
| this.basePath = new Path(config.getBasePath()); | ||
| this.smallFilesMap = new HashMap<>(); | ||
| this.recordsPerBucket = config.getCopyOnWriteInsertSplitSize(); | ||
| this.metaClient = StreamerUtil.createMetaClient( | ||
| config.getBasePath(), context.getStorageConf().unwrapAs(Configuration.class)); | ||
| this.metadataCache = new HashMap<>(); | ||
|
|
@@ -134,35 +133,46 @@ public WriteProfile(HoodieWriteConfig config, HoodieFlinkEngineContext context) | |
| * Obtains the average record size based on records written during previous commits. Used for estimating how many | ||
| * records pack into one file. | ||
| */ | ||
| private long averageBytesPerRecord() { | ||
| protected long averageBytesPerRecord() { | ||
| long avgSize = config.getCopyOnWriteRecordSizeEstimate(); | ||
| long fileSizeThreshold = (long) (config.getRecordSizeEstimationThreshold() * config.getParquetSmallFileLimit()); | ||
| HoodieTimeline commitTimeline = metaClient.getCommitsTimeline().filterCompletedInstants(); | ||
| HoodieTimeline commitTimeline = metaClient.getCommitTimeline().filterCompletedInstants(); | ||
| if (!commitTimeline.empty()) { | ||
| // Go over the reverse ordered commits to get a more recent estimate of average record size. | ||
| Iterator<HoodieInstant> instants = commitTimeline.getReverseOrderedInstants().iterator(); | ||
| while (instants.hasNext()) { | ||
| HoodieInstant instant = instants.next(); | ||
| final HoodieCommitMetadata commitMetadata = | ||
| this.metadataCache.computeIfAbsent( | ||
| instant.requestedTime(), | ||
| k -> WriteProfiles.getCommitMetadataSafely(config.getTableName(), basePath, instant, commitTimeline) | ||
| .orElse(null)); | ||
| if (commitMetadata == null) { | ||
| continue; | ||
| } | ||
| long totalBytesWritten = commitMetadata.fetchTotalBytesWritten(); | ||
| long totalRecordsWritten = commitMetadata.fetchTotalRecordsWritten(); | ||
| if (totalBytesWritten > fileSizeThreshold && totalRecordsWritten > 0) { | ||
| avgSize = (long) Math.ceil((1.0 * totalBytesWritten) / totalRecordsWritten); | ||
| break; | ||
| } | ||
| long sizeFromCommitMetadata = calculateRecordSizeThroughCommitMetadata(commitTimeline, 1.0D); | ||
| if (sizeFromCommitMetadata > 0) { | ||
| avgSize = sizeFromCommitMetadata; | ||
| } | ||
| } | ||
| log.info("Refresh average bytes per record => " + avgSize); | ||
| return avgSize; | ||
| } | ||
|
|
||
| protected long calculateRecordSizeThroughCommitMetadata(HoodieTimeline commitTimeline, double fileSizeCalibrationRatio) { | ||
| long fileSizeThreshold = recordSizeEstimationFileSizeThreshold(); | ||
| // Go over the reverse ordered commits to get a more recent estimate of average record size. | ||
| Iterator<HoodieInstant> instants = commitTimeline.getReverseOrderedInstants().iterator(); | ||
| while (instants.hasNext()) { | ||
| HoodieInstant instant = instants.next(); | ||
| final HoodieCommitMetadata commitMetadata = | ||
| this.metadataCache.computeIfAbsent( | ||
| instant.requestedTime(), | ||
| k -> WriteProfiles.getCommitMetadataSafely(config.getTableName(), basePath, instant, commitTimeline) | ||
| .orElse(null)); | ||
| if (commitMetadata == null) { | ||
| continue; | ||
| } | ||
| long totalBytesWritten = commitMetadata.fetchTotalBytesWritten(); | ||
| long totalRecordsWritten = commitMetadata.fetchTotalRecordsWritten(); | ||
| if (totalBytesWritten > fileSizeThreshold && totalRecordsWritten > 0) { | ||
| return (long) Math.ceil((fileSizeCalibrationRatio * totalBytesWritten) / totalRecordsWritten); | ||
| } | ||
| } | ||
| return -1L; | ||
| } | ||
|
|
||
| private long recordSizeEstimationFileSizeThreshold() { | ||
| return (long) (0.1D * config.getParquetSmallFileLimit()); | ||
| } | ||
|
|
||
| /** | ||
| * Returns a list of small files in the given partition path. | ||
| * | ||
|
|
@@ -228,10 +238,8 @@ private void cleanMetadataCache(Stream<HoodieInstant> instants) { | |
|
|
||
| private void recordProfile() { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤖 Removing the - AI-generated; verify before applying. React 👍/👎 to flag quality. |
||
| this.avgSize = averageBytesPerRecord(); | ||
| if (config.shouldAllowMultiWriteOnSameInstant()) { | ||
| this.recordsPerBucket = config.getParquetMaxFileSize() / avgSize; | ||
| log.info("Refresh insert records per bucket => " + recordsPerBucket); | ||
| } | ||
| this.recordsPerBucket = config.getParquetMaxFileSize() / avgSize; | ||
|
danny0405 marked this conversation as resolved.
|
||
| log.info("Refresh insert records per bucket => " + recordsPerBucket); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: |
||
| } | ||
|
|
||
| /** | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: