-
Notifications
You must be signed in to change notification settings - Fork 23
feat(realtime): add primary-key in-memory support #224
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
Open
HaHaJeff
wants to merge
24
commits into
apache:main
Choose a base branch
from
HaHaJeff:jeff/pk-realtime-v1
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
3a19320
feat(realtime): add primary-key in-memory writes
HaHaJeff 789da66
feat(read): merge primary-key realtime memory with snapshots
HaHaJeff 03ede35
test(realtime): cover primary-key realtime lifecycle
HaHaJeff 3e25630
refactor(realtime): consolidate PK state and validation
HaHaJeff 9f6c99d
fix(read): close PK realtime query readers
HaHaJeff 15d7c91
fix(realtime): close rejected plugin readers
HaHaJeff 2df7b78
fix(read): preserve PK reader metrics after close
HaHaJeff 7148081
refactor(realtime): colocate PK realtime option validation
HaHaJeff 8273045
test(realtime): improve primary key coverage
HaHaJeff 728b97e
fix(realtime): prevent sequence reuse and align nested projections
HaHaJeff f3df0e3
fix(realtime): align PK reads across schema changes
HaHaJeff 3358304
fix(realtime): align PK projections by field ID
HaHaJeff 8d96153
refactor(mergetree): accept sorted key-value readers
HaHaJeff df322c1
feat(realtime): adapt prepared primary-key batches
HaHaJeff 87e4548
refactor(realtime): prepare primary-key batches in framework
HaHaJeff ea90f89
refactor(realtime): simplify primary-key write preparation
HaHaJeff 53f6b02
test(mergetree): reuse reader failure mock
HaHaJeff 141099c
fix(realtime): preserve PK sequence across writer handoff
HaHaJeff a4f9a0c
refactor(realtime): simplify primary key merge readers
HaHaJeff d983089
fix(realtime): validate PK reader contracts
HaHaJeff a9aaa4e
refactor(realtime): simplify reader lifecycle cleanup
HaHaJeff 8ab9817
fix(realtime): harden primary-key prepared batches
HaHaJeff 75f959a
refactor(realtime): simplify primary-key contracts
HaHaJeff 3f0efba
fix(realtime): strengthen primary-key recovery coverage
HaHaJeff File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
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
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
Oops, something went wrong.
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.
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.
Thank you for the contribution. The code looks clear and well organized. Before diving into the detailed review, I would like to discuss two design points.
First, it seems that internal sequence-number assignment and per-batch primary-key sorting are currently handled inside the realtime store implementation. I suggest moving these responsibilities into the Paimon framework instead.
The framework could assign offsets and sequence numbers, append internal fields such as
_VALUE_KIND,_SEQUENCE_NUMBER, and_REALTIME_OFFSET, and physically sort each input Arrow batch before passing it to the store plugin. The plugin would then only manage storage concerns, without needing to understand PK sorting rules, sequence fields, or merge-engine semantics.Query and prepare-commit could convert these already sorted batches into
KeyValueRecordReaders and reuse the existingSortMergeReaderand merge functions. The flush path could also accept sorted readers directly, avoiding sequence reassignment and repeated per-batch sorting. This would make custom plugins easier to implement and allow realtime reads and writes to reuse the framework’s existing merge-engine and sequence-field behavior.I think this can be the first-stage solution. If profiling later shows that copying data to produce physically sorted Arrow batches is a real write-path bottleneck, we could introduce a shallow-copy mode based on sorted indices. That would require significantly more interface changes, so I suggest optimizing it only after it becomes an observed hotspot.
Second, the in-memory store could keep PK statistics for each batch, such as min/max values. Predicates on value fields may not be pushable, but
predicate_for_keysshould be applicable to these statistics so irrelevant in-memory batches can be pruned during reads. This optimization could also be implemented in a follow-up PR.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.
Thanks for the detailed suggestion. I agree that sequence assignment, PK sorting, and merge semantics should belong to the Paimon framework rather than the real-time store plugin.
The current implementation assigns sequence numbers and performs PK sorting and in-memory merging inside the PK store. During prepare-commit, it converts the returned batches back into ordinary
RecordBatches and passes them throughWriteBuffer, which assigns sequence numbers and sorts the same data again. I plan to revise this design as follows.Framework-side batch preparation
Before calling
RealtimeStore::Write, the Paimon framework will:_REALTIME_OFFSETand_SEQUENCE_NUMBERatomically according to the original per-row write order;_VALUE_KIND,_SEQUENCE_NUMBER, and_REALTIME_OFFSET;All columns will be reordered with the same sort indices, so the value, row kind, sequence number, and real-time offset remain associated with the same mutation.
Sorting will not perform deduplication or early MOR. Every mutation will remain in the prepared batch. The progress counters will advance only after
RealtimeStore::Writesucceeds.RealtimeStore responsibility
RealtimeStorewill treat the internal fields as opaque Arrow columns and preserve the prepared batches through write, seal, read-view, query-reader, and commit-reader operations.It will no longer:
Each physically sorted input batch will represent one independent sorted run. A store may return multiple readers, and Paimon will merge those runs in the framework. The built-in and custom stores will therefore use the same path.
Query path
The framework will provide an adapter from the store's
BatchReadertoKeyValueRecordReader.For PK queries:
_REALTIME_OFFSETto remove memory rows already covered by the selected snapshot;KeyValueRecordReaders;SortMergeReadermerges the memory readers with disk readers;_SEQUENCE_NUMBERremains the row-version field used to resolve versions during disk-memory MOR.Prepare-commit path
RealtimeStoreandMergeTreeWriterwill not depend on each other directly. The framework-ownedRealtimePrimaryKeyWriterwill coordinate them:RealtimeStore::SealForCommitto obtain an immutable segment;RealtimeStore::CreateCommitReadersfor that segment;BatchReaders into sortedKeyValueRecordReaders;MergeTreeWriter::WriteSortedReaders;MergeTreeWriter::PrepareCommit;The resulting path will be:
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.
Thank you for your response! The current direction looks good to me. @zjw1111 , could you also take a look?
Also, the offset filtering for PK tables has now been moved to the framework layer, while for append tables it is still handled inside the plugin through the
offset_beginparameter inCreateQueryReaders. I plan to align the append-table path later as well, similar to PK tables, by moving the offset filtering into the framework layer. For this PR, I think it’s fine to keep the current interface for now and focus on implementing the PK-table part first.Uh oh!
There was an error while loading. Please reload this page.
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.
LGTM