Skip to content

fix(writer): bound a parquet file by its truncated row group statistics - #3537

Open
sankarreddy-atlan wants to merge 4 commits into
apache:mainfrom
sankarreddy-atlan:fix/parquet-truncated-stats-bounds
Open

sankarreddy-atlan wants to merge 4 commits into
apache:mainfrom
sankarreddy-atlan:fix/parquet-truncated-stats-bounds

Conversation

@sankarreddy-atlan

Copy link
Copy Markdown

Which issue does this PR close?

What changes are included in this PR?

MinMaxColAggregator now uses truncated string and binary statistics. A truncated min is a prefix, and parquet-rs increments a truncated max, so both are valid bounds.

These cases leave the column with no file bound on that side:

  • A truncated value of another type, such as a fixed longer than 64 bytes. Its length is wrong.
  • A row group without statistics, as in Java's ParquetMetrics.

Long strings in single row group files now get the 64-byte truncated bounds. This does not fix the position delete file_path case in #3464, because the lower and upper bounds are still not equal.

Are these changes tested?

Yes.

  • test_truncated_statistics_bound_the_file writes two row groups. A 100-byte string is the min of one and another is the max of the other. It fails on main with lower bound "b".
  • Two aggregator unit tests: a truncated fixed column gets no bounds, even when a later row group has an exact max. A row group without statistics drops both bounds, even when a later row group has values.

ParquetWriter cannot write a file where only some row groups have statistics, so the writer loop's call to drop_bounds has no end-to-end test.

AI Disclosure

This PR was prepared with AI assistance and reviewed/tested by the author.

parquet-rs truncates string and binary column chunk statistics to 64
bytes and marks them inexact. MinMaxColAggregator skipped inexact
statistics, so in a file with several row groups the file bound could
exclude a value of the file, and bounds-based pruning dropped rows.

A truncated string or binary min is a prefix and a truncated max is
incremented, so both are valid bounds and are now used. A truncated value
of another type, or a row group without statistics, leaves the column
without a file bound on that side, as Java's ParquetMetrics does.
@sankarreddy-atlan

Copy link
Copy Markdown
Author

Hello @kevinjqliu , Could you please review this ?

@JeonDaehong JeonDaehong left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ran a probe on f68070f: 1500 files of random strings and binaries (1 to 4 byte UTF-8 including U+FFFF and U+10FFFF, binaries with runs of 0xFF, 1 to 4 rows per row group). With this PR every value falls inside the file's bounds. On e4f928a, 363 files got a string lower bound and 458 a string upper bound that excluded a value in the file (392 and 33 for binary). The parquet_writer tests pass too.

On #3464: agreed, a single-file position delete still gets unequal file_path bounds after truncation, so they can't tell which data file it refers to. I'll follow up on that on the position delete writer side.

…ed-stats-bounds

# Conflicts:
#	crates/iceberg/src/writer/file_writer/parquet_writer.rs

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Parquet writer writes file bounds that exclude rows when row group statistics are truncated

2 participants