Skip to content

Docs: Add docs for Table Maintenance in Flink - #13771

Closed
JeonDaehong wants to merge 4 commits into
apache:mainfrom
JeonDaehong:main
Closed

JeonDaehong wants to merge 4 commits into
apache:mainfrom
JeonDaehong:main

Conversation

@JeonDaehong

@JeonDaehong JeonDaehong commented Aug 9, 2025 •

Copy link
Copy Markdown
Contributor

This PR adds documentation for issue
( Docs update for Flink Table Maintenance API - Fixes #13307 )

It incorporates feedback received from the previously closed PR #13360.

Please review and let me know if any changes are needed. I will update promptly.

- Introduced comprehensive documentation for Flink Table Maintenance in Apache Iceberg.
- Covers automated snapshot expiration, file compaction, and orphan file cleanup.
- Includes configuration options, examples, scheduling, and best practices.
- Provides lock management details and troubleshooting tips.
@github-actions github-actions Bot added the docs label Aug 9, 2025
@JeonDaehong

JeonDaehong commented Aug 9, 2025 •

Copy link
Copy Markdown
Contributor Author

@pvary @Guosmilesmile
I apologize for the delay in submitting the updated PR due to personal reasons.

@Guosmilesmile Guosmilesmile 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.

@JeonDaehong Thank you very much for your PR! Regarding the documentation part, I feel there are a few points that need to be discussed:

  1. A new md file was added but not included in mkdocs.yml. I think this page will not take effect. I feel it might be unnecessary to add a new page; instead, we could add the content to the existing flink-actions.md, distinguishing between streaming and batch. However, this is just my personal opinion, and I would like to hear @pvary Peter’s thoughts.

  2. Could we add a section about which table maintenance operations Flink currently supports, what their purposes are, and describe the corresponding configurations within each relevant feature, rather than putting all configurations in one section?

  3. Regarding the locking part, there is no Java API configuration provided; the configuration options given are for SQL, and SQL only uses them when compaction is enabled in sink v2. I suggest separating this and describing it in an independent section.

Comment thread docs/docs/flink-table-maintenance.md Outdated
```java
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
TableLoader tableLoader = TableLoader.fromHadoopTable("path/to/table");
TriggerLockFactory lockFactory = TriggerLockFactory.defaultLockFactory();

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.

I think we do not have a method called defaultLockFactory; instead, we need to create a specific LockFactory.

Comment on lines +79 to +83
| `scheduleOnCommitCount(int)` | Trigger after N commits | No automatic scheduling | int |
| `scheduleOnDataFileCount(int)` | Trigger after N data files | No automatic scheduling | int |
| `scheduleOnDataFileSize(long)` | Trigger after total data file size (bytes) | No automatic scheduling | long |
| `scheduleOnIntervalSecond(long)` | Trigger after time interval (seconds) | No automatic scheduling | long |
| `parallelism(int)` | Parallelism for this specific task | Inherits from TableMaintenance | int |

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.

Can we extract the common configurations belonging to the MaintenanceTaskBuilder, instead of having them appear in each functional configuration separately?

Comment thread docs/docs/flink-table-maintenance.md Outdated
Comment on lines +102 to +113

You can also configure maintenance behavior through Flink configuration:

| Configuration Key | Description | Default Value | Type |
|-------------------|-------------|---------------|------|
| `iceberg.maintenance.rate-limit-seconds` | Rate limit in seconds | 60 | long |
| `iceberg.maintenance.lock-check-delay-seconds` | Lock check delay in seconds | 30 | long |
| `iceberg.maintenance.rewrite.max-bytes` | Maximum rewrite bytes | Long.MAX_VALUE | long |
| `iceberg.maintenance.rewrite.schedule.commit-count` | Schedule on commit count | 10 | int |
| `iceberg.maintenance.rewrite.schedule.data-file-count` | Schedule on data file count | 1000 | int |
| `iceberg.maintenance.rewrite.schedule.data-file-size` | Schedule on data file size | 100GB | long |
| `iceberg.maintenance.rewrite.schedule.interval-second` | Schedule interval in seconds | 600 | long |

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.

From my perspective, this part seems a bit strange. How is it used? I can't think of where these configurations come from.

Comment thread docs/docs/flink-table-maintenance.md Outdated

| Method | Description | Default Value | Type |
|--------|-------------|---------------|------|
| `maxSnapshotAge(Duration)` | Maximum age of snapshots to retain | No limit | Duration |

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.

Default value is 5 days ago

Comment thread docs/docs/flink-table-maintenance.md Outdated
Comment on lines +92 to +97
| `partialProgressEnabled(boolean)` | Enable partial progress commits | false | boolean |
| `partialProgressMaxCommits(int)` | Maximum commits for partial progress | 10 | int |
| `scheduleOnCommitCount(int)` | Trigger after N commits | 10 | int |
| `scheduleOnDataFileCount(int)` | Trigger after N data files | 1000 | int |
| `scheduleOnDataFileSize(long)` | Trigger after total data file size (bytes) | 100GB | long |
| `scheduleOnIntervalSecond(long)` | Trigger after time interval (seconds) | 600 (10 minutes) | long |

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.

Same note as above.

Comment thread docs/docs/flink-table-maintenance.md Outdated
| Method | Description | Default Value | Type |
|--------|-------------|---------------|------|
| `targetFileSizeBytes(long)` | Target size for rewritten files | Table property or 512MB | long |
| `partialProgressEnabled(boolean)` | Enable partial progress commits | false | boolean |

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.

Perhaps "Enable partial progress commits, allowing compacted data files to be committed in batches." would be easier to understand.




### RewriteDataFiles Configuration

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.

Some configurations are still missing from the documentation:
minFileSizeBytes
maxFileSizeBytes
minInputFiles
deleteFileThreshold
rewriteAll
maxFileGroupSizeBytes
maxFilesToRewrite
filter

Comment thread docs/docs/flink-table-maintenance.md Outdated
Comment on lines +162 to +183
## Scheduling Options

Maintenance tasks can be triggered based on various conditions:

### Time-based Scheduling
```java
ExpireSnapshots.builder()
.scheduleOnIntervalSecond(3600)
```

### Commit-based Scheduling
```java
RewriteDataFiles.builder()
.scheduleOnCommitCount(50)
```

### Data Volume-based Scheduling
```java
RewriteDataFiles.builder()
.scheduleOnDataFileCount(500)
.scheduleOnDataFileSize(50L * 1024 * 1024 * 1024)
```

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.

It would be better to integrate these with the common configuration section provided above.

Comment thread docs/docs/flink-table-maintenance.md Outdated
Comment on lines +194 to +199
.addPostCommitTopology(
TableMaintenance.forTable(env, tableLoader, TriggerLockFactory.defaultLockFactory())
.rateLimit(Duration.ofMinutes(10))
.add(ExpireSnapshots.builder().scheduleOnCommitCount(10))
.add(RewriteDataFiles.builder().scheduleOnDataFileCount(50))
)

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I have reviewed it. Thank you !

Comment thread docs/docs/flink-table-maintenance.md Outdated
Comment on lines +250 to +270
## Troubleshooting

### Common Issues

**OutOfMemoryError during file deletion:**
```java
.deleteBatchSize(500)
```

**Lock conflicts:**
```java
.lockCheckDelay(Duration.ofMinutes(1))
.rateLimit(Duration.ofMinutes(10))
```

**Slow rewrite operations:**
```java
.partialProgressEnabled(true)
.partialProgressMaxCommits(3)
.maxRewriteBytes(1024 * 1024 * 1024)
``` No newline at end of file

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.

What is the specific scenario here? Providing numerical recommendations directly without detailed reasoning can seem a bit odd.

@JeonDaehong

Copy link
Copy Markdown
Contributor Author

@JeonDaehong Thank you very much for your PR! Regarding the documentation part, I feel there are a few points that need to be discussed:

  1. A new md file was added but not included in mkdocs.yml. I think this page will not take effect. I feel it might be unnecessary to add a new page; instead, we could add the content to the existing flink-actions.md, distinguishing between streaming and batch. However, this is just my personal opinion, and I would like to hear @pvary Peter’s thoughts.
  2. Could we add a section about which table maintenance operations Flink currently supports, what their purposes are, and describe the corresponding configurations within each relevant feature, rather than putting all configurations in one section?
  3. Regarding the locking part, there is no Java API configuration provided; the configuration options given are for SQL, and SQL only uses them when compaction is enabled in sink v2. I suggest separating this and describing it in an independent section.

@Guosmilesmile
Thank you for your feedback.

Based on your comments, I will make the necessary changes and commit them again.

First, I will continue adding the content to the flink-table-maintenance.md file and update the mkdocs.yml file accordingly.

If @pvary prefers the content to be appended to flink-action.md instead, I will revise it and move it there at that time.

Thank you.

docs: add flink-table-maintenacne
Based on the maintainer's feedback, I have revised the content.
@JeonDaehong

Copy link
Copy Markdown
Contributor Author

Hello :D
Sorry to keep asking when you’re busy. Would it be alright if I asked for your feedback when you have time?

@Guosmilesmile @pvary
I have made revisions based on the feedback you provided. Since this is my first time contributing directly to the docs, I appreciate your understanding if there are any shortcomings.

If you have any further feedback, I will gladly make additional updates accordingly.

Also, I have added the entry to the yml file for now. However, if @pvary suggests that it would be better to add this content to flink-actions.md, I will revise it to include it under the actions section.

Thank you always for your help! :D

@Guosmilesmile

Copy link
Copy Markdown
Contributor

Sorry, I've been quite busy lately. I'll find some time to review it in a few days.

@JeonDaehong

Copy link
Copy Markdown
Contributor Author

Sorry, I've been quite busy lately. I'll find some time to review it in a few days.

Please take a look whenever you have time. 😄
Thank you as always for your attention whenever I open a PR.

I have reviewed all the work you’ve done in your recent PRs. It seems you’ve been working quite busily lately.

I’ll also continue to study hard and contribute through PRs so that I can become a Maintainer and take part in the core development of Iceberg’s code. 😄

@Guosmilesmile Guosmilesmile 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.

Many of the configuration items need to be rechecked for their default values. Thank you.

Comment on lines +40 to +41
jdbcProps.put("user", "flink");
jdbcProps.put("password", "flinkpw");

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.

I think this part should be jdbc.user and jdbc.password .

Comment on lines +86 to +89
| `scheduleOnCommitCount(int)` | Trigger after N commits | No automatic scheduling | int |
| `scheduleOnDataFileCount(int)` | Trigger after N data files | No automatic scheduling | int |
| `scheduleOnDataFileSize(long)` | Trigger after total data file size (bytes) | No automatic scheduling | long |
| `scheduleOnIntervalSecond(long)` | Trigger after time interval (seconds) | No automatic scheduling | long |

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.

The configuration here is not complete, and there is no scheduleOnIntervalSecond . It should be scheduleOnInterval. Can we refer to https://github.com/apache/iceberg/blob/main/flink/v2.0/flink/src/main/java/org/apache/iceberg/flink/maintenance/api/MaintenanceTaskBuilder.java for adjustment?

| `maxRewriteBytes(long)` | Maximum bytes to rewrite per execution | Long.MAX_VALUE | long |


### Scheduling Examples

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.

I personally think that the "Scheduling Examples" section is not necessary. Instead, we could add a part before "Configuration Options" to explain which table maintenance features are currently supported by Flink. Each feature could be explained separately, detailing how to use it, somewhat like this: https://iceberg.incubator.apache.org/docs/nightly/spark-procedures/#expire_snapshots

| `retainLast(int)` | Minimum number of snapshots to retain | 1 | int |
| `deleteBatchSize(int)` | Number of files to delete in each batch | 1000 | int |
| `planningWorkerPoolSize(int)` | Number of worker threads for planning snapshot expiration | System default | int |
| `cleanExpiredMetadata(boolean)` | Remove expired metadata files when expiring snapshots | true | boolean |

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.

I think the default value is false, please help to check it agin ,thanks

| `minFileSizeBytes(long)` | Minimum size of files eligible for compaction | 0 | long |
| `maxFileSizeBytes(long)` | Maximum size of files eligible for compaction | Long.MAX_VALUE | long |
| `minInputFiles(int)` | Minimum number of files to trigger rewrite | 1 | int |
| `deleteFileThreshold(double)` | Fraction of delete files to trigger rewrite | 0.0 | double |

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.

Defaults to Integer.MAX_VALUE, which means this feature is not enabled by default.

```


## Flink Configuration Options

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.

I think the content of this part is incorrect, and it is not necessary.

Comment on lines +245 to +251
IcebergSink.forRowData(dataStream)
.table(table)
.tableLoader(tableLoader)
.setAll(flinkConf)
.append();
```

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.

It would be great if we could add some examples for the SQL part.

Comment on lines +260 to +265
flink-maintenance.lock.type=jdbc
flink-maintenance.lock.lock-id=catalog.db.table
flink-maintenance.lock.jdbc.uri=jdbc:postgresql://localhost:5432/iceberg
flink-maintenance.lock.jdbc.user=flink
flink-maintenance.lock.jdbc.password=flinkpw
flink-maintenance.lock.jdbc.init-lock-tables=true

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 is only used in SQL and is only applicable when writing with compression. I suggest presenting the configuration items in a tabular format.

Comment on lines +272 to +278
flink-maintenance.lock.type=zookeeper
flink-maintenance.lock.zookeeper.uri=zk://zk1:2181,zk2:2181
flink-maintenance.lock.zookeeper.session-timeout-ms=60000
flink-maintenance.lock.zookeeper.connection-timeout-ms=15000
flink-maintenance.lock.zookeeper.max-retries=3
flink-maintenance.lock.zookeeper.base-sleep-ms=3000
```

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.

Same note as above.

flink-maintenance.lock.zookeeper.max-retries=3
flink-maintenance.lock.zookeeper.base-sleep-ms=3000
```
Use ZooKeeper-based locks only in high-availability or multi-process coordination environments.

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.

I feel that this is not necessary.

@JeonDaehong

Copy link
Copy Markdown
Contributor Author

Many of the configuration items need to be rechecked for their default values. Thank you.

Thank you for the feedback.
I’ll check and fix it.

I’ll also review the default values in the related classes. :D

@JeonDaehong JeonDaehong closed this by deleting the head repository Aug 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add docs for Table Maintenance in Flink

2 participants