feat(spark-3.5): [stacked] Add VACUUM SQL extension for Iceberg table maintenance - #661
Draft
mkuchenbecker wants to merge 5 commits into
Draft
feat(spark-3.5): [stacked] Add VACUUM SQL extension for Iceberg table maintenance#661mkuchenbecker wants to merge 5 commits into
mkuchenbecker wants to merge 5 commits into
Conversation
Draft
11 tasks
mkuchenbecker
commented
Jul 24, 2026
mkuchenbecker
commented
Jul 24, 2026
mkuchenbecker
commented
Jul 24, 2026
mkuchenbecker
commented
Jul 24, 2026
mkuchenbecker
commented
Jul 24, 2026
8 tasks
Adds a VACUUM command to the OpenHouse spark-3.5 SQL extensions: VACUUM <table> [REMOVE ORPHAN FILES] [RETAIN n HOURS] Snapshot expiration always runs; REMOVE ORPHAN FILES opts into orphan-file deletion, run after expiration so it cleans against the settled live-file set. RETAIN n HOURS bounds both operations via the procedures' older_than argument (resolved to a literal timestamp in the session time zone, since procedure arguments must be foldable); when omitted, each procedure applies its own default retention. Implemented as thin sugar over the Iceberg stored-procedure CALL path: VacuumTableExec validates the target is an OpenHouse table (openhouse.tableId property) and issues CALL <catalog>.system.expire_snapshots / remove_orphan_files via sparkSession.sql(...), so procedure resolution and argument binding reuse the existing CALL path. New non-reserved keywords VACUUM/REMOVE/ORPHAN/FILES/RETAIN/ HOURS; existing identifiers with those names still parse. Tested by VacuumStatementTest (real Iceberg, Hadoop catalog): RETAIN 0 HOURS collapses three snapshots to one with rows intact, REMOVE ORPHAN FILES RETAIN 24 HOURS preserves live data, default retention, lower-case, non-OpenHouse-table rejection, and invalid-syntax parse errors. Co-authored-by: Copilot <[email protected]>
Snapshot expiration commits table metadata and therefore cannot run on a table that is out of quota, whereas orphan-file deletion only removes unreferenced files from storage and always can. Running orphan removal first ensures it still executes in that case, and scanning against the pre-expiration referenced-file set means it can never delete a file a still-live snapshot references. Co-authored-by: Copilot <[email protected]>
VACUUM is an Alpha feature and is now opt-in per table. A table must set 'openhouse.vacuum.enabled' = 'true'; otherwise VACUUM throws UnsupportedOperationException explaining how to enable it. - VacuumTableExec: add the openhouse.vacuum.enabled gate + ENABLED_PROP constant. - VacuumStatementTest: enable the property on the vacuumed table and add testVacuumNotEnabledThrows for an OpenHouse table that has not opted in. - Add public documentation (docs/VACUUM.md): behavior, syntax, the Alpha opt-in knob, merge-on-read handling, examples, and caveats. Co-authored-by: Copilot <[email protected]>
Co-authored-by: Mike Kuchenbecker <[email protected]>
When RETAIN is omitted, VACUUM previously fell back to the Iceberg procedure defaults (5-day snapshot expiration, 3-day orphan-file deletion). Wire the cutoffs to the correct OpenHouse table properties instead, with no change to what the command does (it still cleans reclaimed files via the CALL procedures' default behavior): - Snapshot expiration honors the history policy in the 'policies' property: older_than = now - maxAge x granularity, plus retain_last => versions when set (defaults maxAge=3, granularity=DAY, versions=0, matching OpenHouse). - Orphan-file deletion honors 'ofd.one_day_ttl.enabled' (1 day when set, else the 3-day default). An explicit RETAIN n HOURS still overrides both. Pure helpers (ofdRetainDays, parseHistoryRetention, granularityToChrono) are unit-tested in VacuumTableExecTest; VacuumStatementTest.testVacuumHonorsHistoryPolicyVersions proves end-to-end that a history policy of versions=2 keeps exactly 2 snapshots. Co-authored-by: Copilot <[email protected]>
mkuchenbecker
force-pushed
the
mkuchenb/spark35-sql-vacuum
branch
from
July 31, 2026 23:25
efc6820 to
153fc94
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.
OpenHouse spark-3.5 SQL Extensions Stack
Summary
Adds a VACUUM command to Spark 3.5 Openhouse SQL Extensions.
Behaviour:
All files beyond the specified retention that are no longer referenced in the current version are deleted.
REMOVE ORPHAN FILESopts into orphan-file deletion,run before expiration. This is because snapshot expiration can't run on a table out of quota (writes a snapshot), but orphaned file deletion can run. Orphaned file deletion uses a recursive list operation and is expensive. The command may OOM if the Driver is not large enough. We should consider Inventory Lists as an optional input in the future so the operation can be run as a SQL query distributed on the executors.
RETAIN n HOURSbounds both operations via the procedures'older_thanargument (resolved to a literaltimestamp in the session time zone, since procedure arguments must be foldable); when omitted, each procedure falls back to its own default retention.
Thin sugar over the Iceberg stored-procedure
CALLpath:VacuumTableExecvalidates thetarget is an OpenHouse table (
openhouse.tableId) and issuesCALL <catalog>.system.expire_snapshots/remove_orphan_files, so procedure resolutionand argument binding reuse the existing
CALLpath.Changes
New non-reserved keywords
VACUUM/REMOVE/ORPHAN/FILES/RETAIN/HOURS;existing identifiers with those names still parse.
Testing Done
VacuumStatementTest(real Iceberg, Hadoop catalog), 6 tests:RETAIN 0 HOURScollapsesthree snapshots to one with rows intact;
REMOVE ORPHAN FILES RETAIN 24 HOURSpreserveslive data; default retention; lower-case; non-OpenHouse-table rejection; invalid-syntax
parse error.
Additional Information