-
Notifications
You must be signed in to change notification settings - Fork 589
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
feat(storage): store old value in memtable #15301
Conversation
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.
Generally LGTM. But I think we need more documentation in the codes on this feature to ensure people have less contexts on the RFC can get the basic ideas.
kv_pairs.push((key, StorageValue::new_put(value))); | ||
kv_pairs.push((key, SharedBufferValue::Insert(value))); | ||
if let Some(old_values) = &mut old_values { | ||
old_values.push(Bytes::new()); |
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.
Will we have an entry in the old value SST for KeyOp::Insert
?
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.
No. In SharedBufferBatchIterator
, when IS_NEW_VALUE
is false, at the end of the next
call, we will have an extra advance_until_valid_old_value
to skip the KeyOp::Insert
ad0e146
to
43c84c3
Compare
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.
Left some minor comments. Rest LGTM!
} | ||
} | ||
} | ||
table_change_log |
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.
I think it is guaranteed that entries in table_change_log
should have both non-empty new_value
and non-empty old_value
. Can we add an assertion to check that?
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.
Just thought of a corner case, will we generate a old_value
sst if there are only INSERTs in new_value
sst? Correct me if I am wrong, I think we will generate a old_value
sst with no entries in it.
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.
By design, if there is no data, we will still have an empty EpochNewChangeLog
to store the epochs information so that when we replay we won't miss a barrier.
I just checked the code. Currently the sst builder is initialized lazily. So if the payload is append only, the old value imm iterator won't have any output, and then no sst will be built.
HummockValue::Put(val) => val.len(), | ||
HummockValue::Delete => 0, | ||
SharedBufferValue::Insert(val) | SharedBufferValue::Update(val) => { | ||
val.len() |
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.
Should we add size_of_val
here as well?
I hereby agree to the terms of the RisingWave Labs, Inc. Contributor License Agreement.
What's changed and what's your intention?
After #15300 and #15417
In this PR, we will compact and upload the old values of state store when
is_log_store
is enabled.In
SharedBufferBatch
, whenis_log_store
is enabled, an extraold_value
of typeVec<Bytes>
will be used to stored the old value. Thenew_value
of shared buffer batch now stores a new enumSharedBufferValue
. The difference to the previously usedHummockValue
is thatSharedBufferValue
has an extra enum caseUpdate
to indicate that the operation is an update. When the enum isDelete
andUpdate
the value inold_value
will be the corresponding old value, and forInsert
, it means there is no old value for the current key op, and the value will be an empty bytes. Therefore, theold_value
has the same length as thenew_value
.In
SharedBufferBatchIterator
, we add a new generic const boolIS_NEW_VALUE
to indicate whether the iterator is iterating over new value or old value. IfIS_NEW_VALUE
is true, the logic will be the same as original. IfIS_NEW_VALUE
is false, thevalue
method will take the value from theold_value
, and in thenext_call
, we will further advance the iterator to skip the key with op asInsert
, becauseInsert
has no old value.The old value will be compacted to separate SSTs and add to hummock version.
Checklist
./risedev check
(or alias,./risedev c
)Documentation
Release note
If this PR includes changes that directly affect users or other significant modifications relevant to the community, kindly draft a release note to provide a concise summary of these changes. Please prioritize highlighting the impact these changes will have on users.