Repository navigation
test(parquet): add I/O access tests for parquet pruning, filter pushdown and TopK - #27022
Conversation
…ng baseline - Add InstrumentedObjectStore that correlates requested byte ranges to Parquet file structures (footers, page indexes, bloom filters, data pages) - Add test_parquet_bloom_filter_io_baseline using public SessionContext SQL APIs - Use insta snapshot to capture and compare the storage I/O trace - Documents baseline on main where all candidate column Bloom filters are loaded upfront, establishing the target diff for incremental pruning (apache#25811)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Split the Bloom filter I/O test into reusable setup code in tests/parquet/io/mod.rs and the test itself in tests/parquet/io/bloom_filter_io.rs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ushdown and TopK Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@adriangb @Dandandan @zhuqi-lucas and @xudong963 -- I wonder what you think about this style test to illustrate the IO patterns in our existing parquet reader? I am hoping that as we improve the patterns we'll be able to use this style test to more easily document and verify the behavior |
adriangb
left a comment
There was a problem hiding this comment.
I like the idea a lot!
I wonder if there's isn't a more general version of this, e.g. if we added tracing as a dev-dep and sprinkled tracing::debug! around in important places so we could track planning and other operations as well.
zhuqi-lucas
left a comment
There was a problem hiding this comment.
Nice harness, this makes the I/O differences very easy to see. A few small things, none blocking:
- The test files are small enough that "Read Parquet footer" is the whole file (offsets
0..1402/0..838). Inpage_pruning_iothe page index is clearly used (only page 1 is read forid = 5) but never shows up as its own request, whilebloom_filter_ioshows the OffsetIndex as a separate one. A short note (or a file where the footer read does not cover everything) would help readers not assume the page index is free. describe_rangereturns on the first overlapping column chunk, so a coalesced request spanning several chunks would only show the first one.record_requestandrecord_rangetake the lock separately, so with more than one partition theRequest Nlines could interleave with another request's reads. Fine withtarget_partitions = 1today.
Nits: "acess" in the title, and double spaces in the topk_io.rs docs ("TopK filter is", "which proves").
| //! | ||
| //! ```text | ||
| //! row group 0 | ||
| //! ┌──────┬───────┐ |
| Read Bloom filter for column 'b' (rg 0) (offsets 145..192) | ||
| Read data page for column 'a' (rg 0) (offsets 4..51) | ||
| Read data page for column 'b' (rg 0) (offsets 51..98) | ||
| Request 1 |
There was a problem hiding this comment.
I think showing the distinct requests is what is important as that is the actual IO that is generated
| let test = filter_pushdown_test(true).await; | ||
| assert_snapshot!(test.query("SELECT * FROM t WHERE val = 7").await, @r" | ||
| --- Query: SELECT * FROM t WHERE val = 7 (1 rows) --- | ||
| Request 1 |
There was a problem hiding this comment.
I do love seeing this difference
| description: String, | ||
| } | ||
|
|
||
| /// Byte ranges of one column chunk: |
There was a problem hiding this comment.
this is infrastructure to handle tracking what byte ranges mean
I reviewed It is a great idea -- I don't like the use of the tracing crate, but otherwise 👌 |
This is an excellent point -- I actually adjusted the test so that it sets the metadata hint so that it only covers the metadata and not also the bloom filters and offset indexes
Fixex
Fixex
Fixed |
|
I'll merge this in and hopefully we can keep iterating to make the tests easier to understand / cover more |
Main has the merged version of apache#27022. It describes multi-structure reads, sets the metadata size hint to the footer size, and clears the metadata cache before each query. This merge keeps those changes and ports them to the tracing-based harness, then regenerates the snapshots. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Which issue does this PR close?
Rationale for this change
We have several issues / PRs open that contemplate changing the I/O pattern such as
progressive_iooption usingParquetPushDecoder::scan_plan(one-shot row group I/O with pushdown filters) #26387pushdown_filtersandprogressive_ioby default #26418I want to have a test that clearly shows how those proposals effect the scan
What changes are included in this PR?
Add some new tests that show the Parquet I/O patterns. For example I think this is quite clear now the difference in I/O between filter pushdown and not
What is the testing strategy for this PR?
CI
Are there any user-facing changes?
No