Repository navigation
Reduce compaction merge fan-in on OOM and keep partial output - #14
Merged
Merged
Conversation
Compaction merge OOMs come from reading and writing JSON column substreams across all source parts, so halving merge_max_block_size_bytes barely changed peak memory and batches failed after a few retries. On a memory-limit merge failure, halve max_parts_to_merge_at_once (down to 2) instead, stepping at most once per poll. If merges still exceed the memory limit at fan-in 2, stop destination merges and finish through the existing measure-and-upload path: partially merged output is uploaded and an unmerged batch is released unchanged, rather than failing the batch. Also treat observer context cancellation during the stop/alter queries as a normal exit instead of a fatal error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
What changed
Adaptive fan-in instead of block bytes. When a destination merge fails with
MEMORY_LIMIT_EXCEEDED, the compact observer now halvesmax_parts_to_merge_at_once(32 → 16 → 8 → 4 → 2) viaALTER TABLE … MODIFY SETTING, with merges stopped and restarted around it.merge_max_block_size_bytesis no longer changed.One step per poll. Several memory failures that land in the same 5 s poll ran at the same fan-in, so they now cause a single reduction instead of several.
Keep the result instead of failing. If merges still OOM at fan-in 2, the observer runs
SYSTEM STOP MERGESand returns a sentinel.Compactthen cancels only the merge wait and continues through the existing measure-and-upload path used for deadline, shutdown and manual finalize:Both cases log a
compact_memory_exhaustedwarning.Cancellation race fixed. If the merge wait finished while the observer was running the stop or alter queries, the cancelled request was returned as a fatal error. The observer now treats that as a normal exit, matching how it handles cancellation elsewhere. This also affected the old block-bytes path.
The
--compact-max-parts-to-mergehelp text now says it is the starting value.Why
Compaction batches were failing with
destination merge exceeded memory limit with merge_max_block_size_bytes already at minimum 1048576. The traces show that memory goes to JSON (Object/Dynamic/Variant) substream deserialization across source parts, and to opening per-substream writer buffers. Rows per read were already small (1600–8192), so lowering block bytes had little effect. The batch hit the 1 MiB floor after about five OOMs and failed, discarding merges that had already succeeded.Peak memory scales with source parts × substreams, so fan-in is the setting that controls it. Failing the batch is the wrong outcome when the inputs are intact and partial merges are usable.
Reviewer notes
compact_memory_exhaustedlog identifies these cases.SYSTEM STOP MERGESand the failure count. I believeSYSTEM STOP MERGEScancels any running merge and records it insystem.part_logwith error 236 (ABORTED). If so, each fan-in step could add one non-memory failure, and three of those still fail the batch. I haven't checked this against ClickHouse. If "destination merges failed 3 non-memory times" shows up after this change, the fix is to exclude error 236 indestinationFailedMergeSummary.Testing
go mod tidy(no changes)go test ./...go test -race ./internal/rewrite/./e2e/run.shpassed.New and updated tests cover:
Compactcases with OOM at the floor: one where output is reduced (it uploads) and one where nothing merged (inputs come back unchanged).🤖 Generated with Claude Code