Arrow: Fix TIMESTAMP_MILLIS scaling for dictionary-encoded columns#17143
Open
AbdelrahmanElhawary wants to merge 1 commit into
Open
Arrow: Fix TIMESTAMP_MILLIS scaling for dictionary-encoded columns#17143AbdelrahmanElhawary wants to merge 1 commit into
AbdelrahmanElhawary wants to merge 1 commit into
Conversation
367e1f7 to
bbd0ee0
Compare
bbd0ee0 to
c4803a0
Compare
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.
Problem Context
Apache Iceberg supports reading Parquet files with$\times 1000$ ). While this scaling logic works correctly for
TIMESTAMP_MILLISannotations by converting the millisecond values to Iceberg's internal microsecond representation (PLAINencoded pages (viaTimestampMillisReader), it is completely bypassed when a column is entirely dictionary-encoded (e.g., columns with duplicate or low-cardinality values, like a batch extraction timestamp).When this optimization occurs, the values are displayed as incorrect dates in the year 1970 because raw millisecond values are treated as microseconds.
Closes #17135
Root Cause Analysis
In
VectorizedArrowReader#read, the engine checks whether a column segment produces a dictionary-encoded vector:If
dictEncodedis true, the reader completely bypasses the type-specific switch statement—which normally maps toReadType.TIMESTAMP_MILLISand uses the correctTimestampMillisReader. Instead, it shortcuts by populating a genericIntVectorwith raw dictionary IDs and attaches the raw ParquetDictionaryobject straight to theVectorHolderreturned to Spark.When Spark eventually decodes these IDs via
Dictionary#decodeToLong(id), it receives unscaled milliseconds from the raw Parquet metadata, resulting in corrupted timestamps.Solution
The fix intercepts the raw Parquet
DictionaryinsideVectorizedArrowReader#setRowGroupInforight after initialization.If the column's modern
LogicalTypeAnnotationindicates it is aTIMESTAMPwithTimeUnit.MILLISprecision, the dictionary is wrapped in a proxy wrapper. This proxy intercepts calls todecodeToLong(int id)and scales the returned values to microseconds.This approach resolves the bug gracefully:
It fixes the issue on the optimized dictionary-passthrough path.