Repository navigation
Core: Basic fields and schemas for column files - #16285
gaborkaszab wants to merge 6 commits into
Conversation
|
First piece of the column update work: introducing the basic interface of the column updates files, aka column files |
630b00e to
ca3259e
Compare
ca3259e to
e6f7cf6
Compare
681633b to
813d5c0
Compare
|
I opened a thread on dev@ to discuss the metadata structs for column files. Once that's finalized, I'll incorporate the changes here. |
596f6a4 to
6a1cbe9
Compare
6a1cbe9 to
c683e72
Compare
c683e72 to
6222fad
Compare
|
Adjusted field IDs because |
6222fad to
5c04f55
Compare
5c04f55 to
b6ae446
Compare
| this.status = EntryStatus.MODIFIED; | ||
| } | ||
| // Bumping 'dataSequenceNumber' to avoid having both equality deletes and column files. | ||
| this.dataSequenceNumber = null; |
There was a problem hiding this comment.
We discussed bumping the data sequence number when adding column files. We haven't mentioned file seq num, so I'm not bumping it here.
This works if the manifest owning this data file entry bumps its own seq num when adding column files. Let me know if there is any other way achieving this.
There was a problem hiding this comment.
In a previous google doc discussion, @pvary raised the question if we should just bump up the dataSequenceNumber which captures the logical age of the row. Column file should materialize the _last_updated_sequence_number for unmodified rows and leave the modified rows with null value for inheritance. From row lineage perspective, bumping up dataSequenceNumber is correct and simpler semantically.
data sequence number is only used for v2 equality and position delete matching. it seems that we might be able to forbid writing new equality deletes for v4 tables. I also remember some previous discussion on rewriting equality delete and v2 position delete files when adding a new column file. With the writer requirement, it is safe to just bump up the dataSequenceNumber here.
But the comment line is a bit confusing. I would write as following: Reset to null to inherit from the new snapshot sequence number. It is safe to bump up the dataSequenceNumber as writers are required to rewrite v2 equality and position deletes to DVs when applying column update.
There was a problem hiding this comment.
Thanks for the comment suggestion! Added
b6ae446 to
0a252e8
Compare
c303670 to
5d96c17
Compare
anuragmantri
left a comment
There was a problem hiding this comment.
I did another round after adding key_metdata and split_offsets. I think this is ready to be merged.
| if (status == EntryStatus.EXISTING) { | ||
| this.status = EntryStatus.MODIFIED; | ||
| } | ||
| // Bumping 'dataSequenceNumber' to avoid having both equality deletes and column files. |
There was a problem hiding this comment.
Should this comment be?
| // Bumping 'dataSequenceNumber' to avoid having both equality deletes and column files. | |
| // Clears dataSequenceNumber so it re-inherits from the manifest at read time. |
There was a problem hiding this comment.
Thanks for the suggestion! Steven also had one, I went with that.
| assertThat(withDeletedPositions.latestColumnFileSnapshotId()).isEqualTo(999L); | ||
| assertThat(withDeletedPositions.dvSnapshotId()).isEqualTo(999L); | ||
| assertThat(withDeletedPositions.deletedPositions()).isEqualTo(deletedBytes); | ||
|
|
There was a problem hiding this comment.
Should we verify the dataSequenceNumber is null?
| assertThat(withDeletedPositions.dataSequenceNumber()).isNull(); |
Same on L314 and in manifestPositionsWithColumnFilesUpdated() test
| case 5 -> this.keyMetadata = ByteBuffers.toByteArray((ByteBuffer) value); | ||
| case 6 -> this.splitOffsets = ArrayUtil.toLongArray((List<Long>) value); | ||
| default -> { | ||
| // ignore the object, it must be from a newer version of the format |
There was a problem hiding this comment.
nit: should the comment say `ignore the unknown positions, as they must come from a newer version of the format"
There was a problem hiding this comment.
This comment is inline with the same in TrackedFileStruct and TrackingStruct. I'd rather keep consistency with these.
There was a problem hiding this comment.
that's fine for consistency. I found "ignore the object" not very accurate.
| this.status = EntryStatus.MODIFIED; | ||
| } | ||
| // Bumping 'dataSequenceNumber' to avoid having both equality deletes and column files. | ||
| this.dataSequenceNumber = null; |
There was a problem hiding this comment.
In a previous google doc discussion, @pvary raised the question if we should just bump up the dataSequenceNumber which captures the logical age of the row. Column file should materialize the _last_updated_sequence_number for unmodified rows and leave the modified rows with null value for inheritance. From row lineage perspective, bumping up dataSequenceNumber is correct and simpler semantically.
data sequence number is only used for v2 equality and position delete matching. it seems that we might be able to forbid writing new equality deletes for v4 tables. I also remember some previous discussion on rewriting equality delete and v2 position delete files when adding a new column file. With the writer requirement, it is safe to just bump up the dataSequenceNumber here.
But the comment line is a bit confusing. I would write as following: Reset to null to inherit from the new snapshot sequence number. It is safe to bump up the dataSequenceNumber as writers are required to rewrite v2 equality and position deletes to DVs when applying column update.
| Tracking withDeletedPositions = | ||
| TrackingBuilder.from(manifestSourceTracking(), 999L) | ||
| .columnFilesUpdated() | ||
| .deletedPositions(deletedBytes) |
There was a problem hiding this comment.
deletedPositions bitmap is only meant for leaf manifest entry in the root manifest file? Ae we testing the scenario of column update for a leaf manifest file in this test?
There was a problem hiding this comment.
I don't think technically we want to avoid providing deleted/replaced positions together with column files. I just wanted to pin this down with a test.
Giving this some further thought, I think you're right: Such a Tracking that has these positions is an entry in the root manifest pointing to a leaf manifest. I don't think we plan to add column files for leaf manifest at this point, but it seems too strict to reject such a setting.
Could such a test remain? WDYT @stevenzwu ?
There was a problem hiding this comment.
I don't think we plan to add column files for leaf manifest at this point
We will use column files for leaf manifests in v4. we should keep this test.
I was mainly alluding to if we should cover the column update for data file cases, where deletedPositions is not applicable.
There was a problem hiding this comment.
In Tracking and TrackingBuilder we don't really know if it belongs to a data file entry or a manifest entry. There might be implications like presence of deleted positions or dv_snapshot_id but nothing decisive. We can add a separate test where we don't set deleted/replaced positions, but probably it doesn't add much to the coverage.
5d96c17 to
2bdf7bb
Compare
gaborkaszab
left a comment
There was a problem hiding this comment.
Thanks for the reviews @anuragmantri and @stevenzwu ! I believe I addressed all your comments. Would you mind taking another look?
| case 5 -> this.keyMetadata = ByteBuffers.toByteArray((ByteBuffer) value); | ||
| case 6 -> this.splitOffsets = ArrayUtil.toLongArray((List<Long>) value); | ||
| default -> { | ||
| // ignore the object, it must be from a newer version of the format |
There was a problem hiding this comment.
This comment is inline with the same in TrackedFileStruct and TrackingStruct. I'd rather keep consistency with these.
| if (status == EntryStatus.EXISTING) { | ||
| this.status = EntryStatus.MODIFIED; | ||
| } | ||
| // Bumping 'dataSequenceNumber' to avoid having both equality deletes and column files. |
There was a problem hiding this comment.
Thanks for the suggestion! Steven also had one, I went with that.
| this.status = EntryStatus.MODIFIED; | ||
| } | ||
| // Bumping 'dataSequenceNumber' to avoid having both equality deletes and column files. | ||
| this.dataSequenceNumber = null; |
There was a problem hiding this comment.
Thanks for the comment suggestion! Added
| assertThat(withDeletedPositions.latestColumnFileSnapshotId()).isEqualTo(999L); | ||
| assertThat(withDeletedPositions.dvSnapshotId()).isEqualTo(999L); | ||
| assertThat(withDeletedPositions.deletedPositions()).isEqualTo(deletedBytes); | ||
|
|
| Tracking withDeletedPositions = | ||
| TrackingBuilder.from(manifestSourceTracking(), 999L) | ||
| .columnFilesUpdated() | ||
| .deletedPositions(deletedBytes) |
There was a problem hiding this comment.
I don't think technically we want to avoid providing deleted/replaced positions together with column files. I just wanted to pin this down with a test.
Giving this some further thought, I think you're right: Such a Tracking that has these positions is an entry in the root manifest pointing to a leaf manifest. I don't think we plan to add column files for leaf manifest at this point, but it seems too strict to reject such a setting.
Could such a test remain? WDYT @stevenzwu ?
2bdf7bb to
d0509a7
Compare
|
Thanks for the approval @stevenzwu and for the reviews @anuragmantri , @amogh-jahagirdar , @RussellSpitzer! |
c26a609 to
dd2433c
Compare
dd2433c to
b0712b8
Compare
Defines the column_file element struct referenced by the column_files field (158) in the v4 content entry, matching the ColumnFile schema added in apache#16285. Co-authored-by: Gabor Kaszab <gaborkaszab@gmail.com> Co-authored-by: Anurag Mantripragada <amantripragada@apple.com>
Makes the column_files field type list<159: column_file> to match the inline element-id convention used by other list fields in the content entry, matching apache#16285. Co-authored-by: Gabor Kaszab <gaborkaszab@gmail.com> Co-authored-by: Anurag Mantripragada <amantripragada@apple.com>
abbdc88 to
0d37967
Compare
laskoviymishka
left a comment
There was a problem hiding this comment.
Nice work on this. The ColumnFile / ColumnFileStruct split fits the existing DeletionVector / Tracking pattern, and the schema wiring looks consistent with the rest of the file.
I’d still hold the merge on one thing: columnFilesUpdated() resets dataSequenceNumber, and the new inheritFrom() path can then assign a newer value to a MODIFIED entry.
That means attaching a column file can move the data sequence number forward even though the row data did not change. Since delete planning uses that sequence number, this could make existing deletes stop applying and bring deleted rows back.
The comment says this is safe because writers rewrite old deletes to DVs during a column update, but that is not enforced here yet. I think we should either keep the original sequence number for MODIFIED entries, or enforce that precondition here. A short spec note would also help.
A few smaller things:
- no manifest round-trip test covers a populated
column_fileslist internalSetdoes not copycolumnFiles, unlike the constructor and sibling fields- the copy constructor drops null elements instead of preserving the list shape
- a couple of small builder-message / javadoc nits inline
The sequence-number behavior is the main one for me. Once that is settled, I’m happy to take another look.
laskoviymishka
left a comment
There was a problem hiding this comment.
LGTM! Nice work in general.
I think we can merge this to unblock further work on column-updates.
This change introduces the interface for column files and also integrates it to the schema for TrackedFile.
| .toString(); | ||
| } | ||
|
|
||
| static class Builder { |
There was a problem hiding this comment.
Since ColumnFile is something being passed in by the users through the table API, at some point we would want to make some builder public for them. I'd keep this here as long as it's possible and then I'd introduce something like a ColumnFiles class that can be used to produce the ColumnFile objects, similarly to DataFiles
|
Latest changes: |
This change introduces the interface for column files and also integrates it to the schema for TrackedFile.