rapidsai / cudf

cuDF - GPU DataFrame Library
https://docs.rapids.ai/api/cudf/stable/
Apache License 2.0
8.46k stars 908 forks source link

[FEA] Add `encoding_stats` footer metadata to the parquet writer #15313

Closed GregoryKimball closed 7 months ago

GregoryKimball commented 8 months ago

Is your feature request related to a problem? Please describe.

The parquet-cpp-arrow writer includes ColumnChunk encoding_stats after the ColumnChunk statistics in the Parquet file footer. The encoding stats are useful for providing a total page count, tracking RLE_DICTIONARY fallback to PLAIN encoding, and verifying optional V2 encodings such as DELTA_BYTE_ARRAY and DELTA_LENGTH_BYTE_ARRAY.

Parquet-tools is a simple command line interface to learn more about a parquet file.

Here is an example of the encoding_stats data from the writer parquet-cpp-arrow version 14.0.2

df = pd.DataFrame({'a': [1,2]})
df.to_parquet('cpp-arrow.pq')

df = cudf.DataFrame({'a': [1,2]})
df.to_parquet('cudf.pq')

parquet-tools inspect --detail cpp-arrow.pq

■■■■■■■■■■■■■■■■ColumnChunk
■■■■■■■■■■■■■■■■■■■■file_offset = 108
■■■■■■■■■■■■■■■■■■■■meta_data = ColumnMetaData
■■■■■■■■■■■■■■■■■■■■■■■■type = 2
■■■■■■■■■■■■■■■■■■■■■■■■encodings = list
■■■■■■■■■■■■■■■■■■■■■■■■■■■■0
■■■■■■■■■■■■■■■■■■■■■■■■■■■■3
■■■■■■■■■■■■■■■■■■■■■■■■■■■■8
■■■■■■■■■■■■■■■■■■■■■■■■path_in_schema = list
■■■■■■■■■■■■■■■■■■■■■■■■■■■■a
■■■■■■■■■■■■■■■■■■■■■■■■codec = 1
■■■■■■■■■■■■■■■■■■■■■■■■num_values = 2
■■■■■■■■■■■■■■■■■■■■■■■■total_uncompressed_size = 100
■■■■■■■■■■■■■■■■■■■■■■■■total_compressed_size = 104
■■■■■■■■■■■■■■■■■■■■■■■■data_page_offset = 36
■■■■■■■■■■■■■■■■■■■■■■■■dictionary_page_offset = 4
■■■■■■■■■■■■■■■■■■■■■■■■statistics = Statistics
■■■■■■■■■■■■■■■■■■■■■■■■■■■■max = b'\x02\x00\x00\x00\x00\x00\x00\x00'
■■■■■■■■■■■■■■■■■■■■■■■■■■■■min = b'\x01\x00\x00\x00\x00\x00\x00\x00'
■■■■■■■■■■■■■■■■■■■■■■■■■■■■max_value = b'\x02\x00\x00\x00\x00\x00\x00\x00'
■■■■■■■■■■■■■■■■■■■■■■■■■■■■min_value = b'\x01\x00\x00\x00\x00\x00\x00\x00'
■■■■■■■■■■■■■■■■■■■■■■■■encoding_stats = list
■■■■■■■■■■■■■■■■■■■■■■■■■■■■PageEncodingStats
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■page_type = 2
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■count = 1
■■■■■■■■■■■■■■■■■■■■■■■■■■■■PageEncodingStats
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■encoding = 8
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■count = 1

parquet-tools inspect --detail cudf.pq

■■■■■■■■■■■■■■■■ColumnChunk
■■■■■■■■■■■■■■■■■■■■meta_data = ColumnMetaData
■■■■■■■■■■■■■■■■■■■■■■■■type = 2
■■■■■■■■■■■■■■■■■■■■■■■■encodings = list
■■■■■■■■■■■■■■■■■■■■■■■■■■■■0
■■■■■■■■■■■■■■■■■■■■■■■■path_in_schema = list
■■■■■■■■■■■■■■■■■■■■■■■■■■■■a
■■■■■■■■■■■■■■■■■■■■■■■■codec = 1
■■■■■■■■■■■■■■■■■■■■■■■■num_values = 2
■■■■■■■■■■■■■■■■■■■■■■■■total_uncompressed_size = 33
■■■■■■■■■■■■■■■■■■■■■■■■total_compressed_size = 29
■■■■■■■■■■■■■■■■■■■■■■■■data_page_offset = 4
■■■■■■■■■■■■■■■■■■■■■■■■statistics = Statistics
■■■■■■■■■■■■■■■■■■■■■■■■■■■■max_value = b'\x02\x00\x00\x00\x00\x00\x00\x00'
■■■■■■■■■■■■■■■■■■■■■■■■■■■■min_value = b'\x01\x00\x00\x00\x00\x00\x00\x00'
GregoryKimball commented 8 months ago

@etseidl Do you think this would be useful... or is it a waste of bytes?

etseidl commented 8 months ago

Do you think this would be useful... or is it a waste of bytes?

I did a quick look at the parquet-format site to see why it was added. It seems knowing that all pages are dictionary encoded helps with predicate pushdown. I assume you can just decode the dictionary page and eliminate entire column chunks if a filtering condition has no matches. Sounds like a good thing to add.