Implement insertion strategy for merge update in timeseries#3239
Open
vasil-pashov wants to merge 3 commits into
Open
Implement insertion strategy for merge update in timeseries#3239vasil-pashov wants to merge 3 commits into
vasil-pashov wants to merge 3 commits into
Conversation
Phase one of insertion has some limitations that are going to be addressed in future PRs. The limitations are: * Works for timeseries only * String columns are not supported * Does not support a single value spanning multiple segments * Can insert only if the source index value lies in the middle of some existing segment, e.g. if there are 3 segments [5, 20) [20, 25) [30, 50) source rows with indexes 0, 4, 26, 29, 55 cannot be inserted * Segments are not sliced. Insertion can produce large segments. Matching on multiple columns is supported. The algorithm is merges two sorted lists in O(m + n) where m is the size of the segment and n is the size of the source data that lies within this segment. This PR also handles mixed strategy update on match and insert when source row is not matched Handle inserting when the source does not lie in a segment Add more tests Add C++ unit tests Fix tests. Improve structure for processing Code refactor update Get simple case of index value spanning multiple rows working Add more testing Refactor wip Fix tests wip Handle repeated indexes Move split_by_time_slice Add split by time slice test fixture Add tests for split by timeslice Fix test and reformat Add more tests Add rapid check for split by time slice refactor gtest Fix rapidcheck test for good Make rapidcheck test faster Improve rapidcheck test Fix entity generation for repeated entities Fix column spanning multiple row slices Rebase on master Move filter_index_match out of the class and use exponential_binary_search Add C++ tests for long chain of time slices Fix bug in string pool building Fix bugs python tests revelaed Fix bug in initialize_rows_to_update_for_row_range_indexed_data Clean merge interface Implement insertion of strings Fix type mismatch Fix failing C++ tests Fix processing unit's returned row ranges Work on merging slices Fix merging of slices Fix merging of slices Add tests Clean up tests Add insert hypothesis Fix hypothesis Fix more hypothesis bugs Sort unique rows More hypthesis fixes More hypothesis fixes Fix hypothesis Add tests Fix a bug Add test for insert and update Refactor Fix a bug Change map from time range to row range Fix bugs Add cpp tests Remove get_source_data Exit early filtering when there are no target matches left Add comments
Contributor
ArcticDB Code Review SummaryThis PR enables the PR Title & Description
Documentation
Code Quality (minor)
Correctness (informational — not blocking)
|
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.
Merge update - Insert
High level overview
This PR implements both strategies
MergeStrategy("do_nothing", "insert")andMergeStrategy("update", "insert"). Both the source and the target must be DateTime-indexed and ordered. Insertion is stable, meaning that new values will come after values already in the target.Implementation details
Structure by time slice
Only source rows that are not matched by anything in the target are inserted. This means that if an index value appears in more than one segment all segments containing that index value must be loaded by the processing unit. This is implemented in
structure_by_time_slice. This function structures together all segments that contain the same index values. With this change one segment can appear in multiple groups. ExampleWill produce the following groups:
With corresponding time ranges
Note 1. that the procedure intentionally splits the groups so that when segments are chained like so
[a, b] [b, c] [c, d], [d, e]not all segments are loaded in the same processing unit.Note 2. With this approach different processing unit not only can have overlapping index ranges. Two different processing units can have the same index range. Example:
Will create two groups
Both groups span the same index range
[10;31)Note 3. Only the first and last row slice of a group can be requested by more than one processing unit
Note 4. Two processing units will never operate on the same set of data (see
get_target_start_end). If the first row slice of a group has entity fetch count > 1 this means that it's the last row slice of a previous group. This means that the first index value of this row slice was repeated in the previous group. That group will handle this index value. This processing unit must skip the repeated index value. Analogous if the last segment has entity fetch count > 1, it must be cut at the end. Using the example above.Performance consideration
Structure for processing still marks all segments in a time sliced group for loading if there's an index value appearing in the time range of the index group. When this is the value that spans multiple segments this will create more work, as some segments that are not matched will be loaded. Using the example above if the source contains the value
5we'll end up with the following processing unitsClearly only the one in the middle needs actual work.
Merge
The
mergefunction performs both inserting new data and updating matched rows. It produces a single one column. Essentially it is merging of two sorted lists, with the caveat that the target is actually list of lists, not a single list. However all values inconcatenate(target_index)are sorted. The nuisance is that there's additional bookkeeping of which is the current target list.Since the target rows to be updated can be in arbitrary order updating happens in two steps
x(including new values)Merge will also truncate columns so that the output contains only values for which the processing unit is responsible. Using the the example above if the source contains value
5the processing units will beassuming no insertion the output will be
Further work
Currently merging uses the same algorithm for the index and the data columns. A better approach would be to run the current algorithm for the index once and make it produce a recipe of the sort:
and apply this to all columns.
Index reconstruction
The reconstruction of the index key has changed a bit. Up to now there was a
1:1mapping in the slices and keys of the old keys and the new keys because update did not create new data. Now the processing unit will emit different row ranges. The new row ranges will represent the combined row range of the whole group of row slices processed by the segment, it will not account the added rows. The added rows are reported separately in theMergeUpdateInsertedRowsEntitystructure fetched from the component manager.MatchRecord
Helper structure to handle all the matching logic together and encapsulated. The biggest change is that the structure of matched rows is no longer a list of lists (for every source row all target rows that match it). It's list of list of lists. For each row slice for each source source row all target rows that match it.