-
Notifications
You must be signed in to change notification settings - Fork 1.4k
[flink][core] Introduce file-size option in Paimon source #9368
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
base: master
Are you sure you want to change the base?
Changes from all commits
e277dc2
cbeadcb
b609301
2c3980c
b9c546c
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 |
|---|---|---|
|
|
@@ -37,7 +37,10 @@ | |
| import org.apache.paimon.table.source.DataSplit; | ||
| import org.apache.paimon.table.source.PostponeMergePlan; | ||
| import org.apache.paimon.table.source.PostponeMergeReadBuilder; | ||
| import org.apache.paimon.table.source.QueryAuthSplit; | ||
| import org.apache.paimon.table.source.ReadBuilder; | ||
| import org.apache.paimon.table.source.Split; | ||
| import org.apache.paimon.utils.SerializableFunction; | ||
| import org.apache.paimon.utils.StringUtils; | ||
|
|
||
| import org.apache.flink.api.common.eventtime.WatermarkStrategy; | ||
|
|
@@ -219,6 +222,7 @@ private ReadBuilder createReadBuilder(@Nullable org.apache.paimon.types.RowType | |
|
|
||
| private DataStream<RowData> buildStaticFileSource() { | ||
| Options options = Options.fromMap(table.options()); | ||
| validateSplitWeightMode(options); | ||
| return toDataStream( | ||
| new StaticFileStoreSource( | ||
| createReadBuilder(projectedRowType()), | ||
|
|
@@ -227,10 +231,58 @@ private DataStream<RowData> buildStaticFileSource() { | |
| options.get(FlinkConnectorOptions.SCAN_SPLIT_ENUMERATOR_ASSIGN_MODE), | ||
| dynamicPartitionFilteringInfo, | ||
| outerProject(), | ||
| splitWeightFunc(options), | ||
| null, | ||
| options.get(CoreOptions.BLOB_AS_DESCRIPTOR), | ||
| skipPreloadTargetSnapshot)); | ||
| } | ||
|
|
||
| private static SerializableFunction<FileStoreSourceSplit, Long> splitWeightFunc( | ||
| Options options) { | ||
| if (isFileSizeWeightMode(options)) { | ||
| return FlinkSourceBuilder::splitFileSizeOrRowCount; | ||
|
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. [P2] Please assign the largest byte-weighted splits first. The supplied weight is consumed by BinPacking.packForFixedBinNumber, which sorts items in ascending order before placing each item in the lightest bin. With two readers, 100 splits of weight 1, and one split of weight 100, the current algorithm produces loads of 50 and 150, while largest-first placement produces 100 and 100. A large file plus many small files is a realistic case for this option, so the new mode can preserve the long-tail skew it is intended to remove. Please use descending/LPT order for this path (or fix the shared packer if compatible) and add this distribution as a regression test. |
||
| } | ||
| switch (options.get(FlinkConnectorOptions.SCAN_SPLIT_ENUMERATOR_WEIGHT_MODE)) { | ||
| case ROW_COUNT: | ||
| return split -> split.split().rowCount(); | ||
| default: | ||
| throw new UnsupportedOperationException( | ||
| "Unsupported split weight mode " | ||
| + options.get( | ||
| FlinkConnectorOptions.SCAN_SPLIT_ENUMERATOR_WEIGHT_MODE)); | ||
| } | ||
| } | ||
|
|
||
| private static void validateSplitWeightMode(Options options) { | ||
| checkArgument( | ||
| !isFileSizeWeightMode(options) | ||
| || options.get(FlinkConnectorOptions.SCAN_SPLIT_ENUMERATOR_ASSIGN_MODE) | ||
| == FlinkConnectorOptions.SplitAssignMode.FAIR, | ||
| "'%s' = '%s' only works with '%s' = '%s'.", | ||
| FlinkConnectorOptions.SCAN_SPLIT_ENUMERATOR_WEIGHT_MODE.key(), | ||
| FlinkConnectorOptions.SplitWeightMode.FILE_SIZE, | ||
| FlinkConnectorOptions.SCAN_SPLIT_ENUMERATOR_ASSIGN_MODE.key(), | ||
| FlinkConnectorOptions.SplitAssignMode.FAIR); | ||
| } | ||
|
|
||
| private static boolean isFileSizeWeightMode(Options options) { | ||
| return options.get(FlinkConnectorOptions.SCAN_SPLIT_ENUMERATOR_WEIGHT_MODE) | ||
| == FlinkConnectorOptions.SplitWeightMode.FILE_SIZE; | ||
| } | ||
|
|
||
| @VisibleForTesting | ||
| static long splitFileSizeOrRowCount(FileStoreSourceSplit sourceSplit) { | ||
| Split split = sourceSplit.split(); | ||
| while (split instanceof QueryAuthSplit) { | ||
| split = ((QueryAuthSplit) split).split(); | ||
| } | ||
| if (split instanceof DataSplit) { | ||
|
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. [P2] Please preserve file-size weighting through QueryAuthSplit. When query-auth.enabled is true and REST authorization returns a row filter or column mask, TableQueryAuthResult.convertPlan wraps each underlying DataSplit in QueryAuthSplit. This outer-type check then falls back to rowCount, so authenticated bounded reads silently ignore file-size mode even though QueryAuthSplit exposes the wrapped split. Please unwrap transparent QueryAuthSplit layers before checking for DataSplit and add a wrapped-split test. |
||
| return ((DataSplit) split) | ||
| .dataFiles().stream().mapToLong(file -> file.fileSize()).sum(); | ||
| } | ||
| return split.rowCount(); | ||
| } | ||
|
|
||
| private @Nullable DataStream<RowData> buildPostponeMergeSource() { | ||
| FileStoreTable fileStoreTable = (FileStoreTable) table; | ||
| if (fileStoreTable.coreOptions().startupMode() == CoreOptions.StartupMode.COMPACTED_FULL) { | ||
|
|
||
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.
[P2] Apply the weight mode to bounded system-table sources
This option is currently consumed only by FlinkSourceBuilder. SystemTableSource also constructs StaticFileStoreSource for bounded system-table reads and already propagates the batch size and assign mode, but it calls the overload that leaves the weight function null. A query such as a bounded $ro read with scan.split-enumerator.weight-mode=file-size therefore silently continues balancing by row count, and file-size with preemptive is accepted without the documented validation. Please share the parsing/validation and weight function with SystemTableSource (including copy()), or explicitly reject/document the unsupported path, and add a bounded system-table regression test.