feat(hive-sync): batch and parallelize HMS partition operations#18983
Draft
nsivabalan wants to merge 1 commit into
Draft
feat(hive-sync): batch and parallelize HMS partition operations#18983nsivabalan wants to merge 1 commit into
nsivabalan wants to merge 1 commit into
Conversation
Hive sync partition operations on HMS today serialize through a single IMetaStoreClient and ship entire partition lists in a single Thrift call for TOUCH/UPDATE. For large tables (~2k partitions) this is ~5-9x slower than parallel implementations (see apache#18331). The biggest contributors are (1) one giant alter_partitions call for UPDATE/TOUCH, and (2) per- partition Thrift round-trips for DROP, all sequential. This change introduces an opt-in IMetaStoreClientPool gated behind hoodie.datasource.hive_sync.batching.enabled (default false). When on, HMSDDLExecutor splits ADD / UPDATE / TOUCH / DROP into batches of hoodie.datasource.hive_sync.batch_num (existing config, default 1000) and fans them out across a pool of RetryingMetaStoreClient instances sized by hoodie.datasource.hive_sync.batching.threads (default 4). Design invariant: only partition-row operations go through the pool. Table-row operations (createTable, alter_table, last-commit-time-synced, writer-version, table-comments) stay on the existing session client, so there is no lost-update risk on table parameters. The sync flow remains serial-parallel-serial (phase 1: table setup, phase 2: parallel partition fan-out, phase 3: table finalization). Sequential fallback is preserved when the flag is off or when HIVE_SYNC_USE_SPARK_CATALOG is on (incompatible with the pool's direct RetryingMetaStoreClient.getProxy path). Tests: TestIMetaStoreClientPool covers borrow/return, concurrent borrows, close idempotency. TestHiveSyncTool.testHMSSyncWithBatchingEnabled exercises end-to-end sync against the embedded HMS with batching on. Related: apache#18331 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #18983 +/- ##
============================================
+ Coverage 68.26% 68.27% +0.01%
- Complexity 29513 29561 +48
============================================
Files 2542 2543 +1
Lines 142627 142818 +191
Branches 17788 17810 +22
============================================
+ Hits 97369 97516 +147
- Misses 37253 37295 +42
- Partials 8005 8007 +2
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
Collaborator
This was referenced Jun 12, 2026
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.
Summary
IMetaStoreClientPoolfor HMS partition sync (issue #18331)hoodie.datasource.hive_sync.batch_num(default 1000)RetryingMetaStoreClientinstances via a fixed-size executorhoodie.datasource.hive_sync.batching.enabled=trueDesign invariant
Only partition-row operations (
add_partitions,alter_partitions,dropPartition,getPartition) go through the pool. Table-row operations (createTable,alter_table,updateLastCommitTimeSynced,updateHoodieWriterVersion,updateTableComments) stay on the existing sessionIMetaStoreClientheld byHoodieHiveSyncClient. The sync flow is therefore serial → parallel → serial:This eliminates lost-update risk on
Table.parameters(the read-modify-write pattern used byupdateLastCommitTimeSyncedandupdateHoodieWriterVersion).New configs
hoodie.datasource.hive_sync.batching.enabledfalsehoodie.datasource.hive_sync.batching.threads4Reuses the existing
hoodie.datasource.hive_sync.batch_numfor batch sizing (no new batch-size config).Scope
HMS executor only — matches the branch name
hms-parallelize-calls. HiveQL and JDBC executor parallelism is deferred (per-threadSessionState/Driverand JDBCConnectionpools are bigger changes; gating on benchmarks of this PR first).Failure semantics
add_partitions(list, ifNotExists=true),partitionExistsguard beforedropPartition, idempotentalter_partitions), so partial-state retry behavior matches today.Compatibility
When
HIVE_SYNC_USE_SPARK_CATALOG=true, the pool path is skipped with a warning and we fall back to sequential — the reflection-builtSparkCatalogMetaStoreClientisn't compatible with the directRetryingMetaStoreClient.getProxyconstruction path.Test plan
mvn compileonhudi-sync/hudi-hive-sync— clean, 0 Checkstyle violations, 0 RAT issuesmvn testonhudi-sync/hudi-hive-sync— 296 tests, 0 failures, 0 errorsTestIMetaStoreClientPool(new, 8 tests) — borrow/return on success, on failure, concurrent borrow bounded by pool size, idempotent close, executor lifecycle, size validationTestHiveSyncTool#testHMSSyncWithBatchingEnabled(new) — end-to-end HMS sync withbatching.enabled=true,threads=3,batch_num=3, 10 initial + 4 incremental partitionsFiles touched
HiveSyncConfigHolder.java— 2 newConfigPropertyconstantsHoodieHiveSyncClient.java— owns + closes the pool, builds it only for HMS mode with flag onddl/HMSDDLExecutor.java— new constructor accepting the pool,runBatcheshelper shared across all four partition methodsutil/IMetaStoreClientPool.java— new; modeled on Iceberg'sHiveClientPoolbut standalone (no Iceberg dep)TestIMetaStoreClientPool.java— new; mock-based unit testsTestHiveSyncTool.java— new end-to-end test methodFollow-ups (separate PRs)
JDBCExecutor.constructDropPartitions). The real JDBC gap isSET LOCATION(UPDATE), which is one statement per partition with no batching.SessionState/Connectioncomplexity.Related: #18331
🤖 Generated with Claude Code