Repository navigation
prototype: capture Parquet scan operations with tracing in I/O tests #27110
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
adriangb
wants to merge
17
commits into
apache:main
Choose a base branch
from
adriangb:io-tracing-prototype
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+838
−310
Draft
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
c0a70fb
test(parquet): add SQL-level I/O snapshot test for Bloom filter loadi…
mohitgurav20 73ba64e
test(parquet): use inline snapshot for Bloom filter I/O test
alamb 37110ee
test(parquet): move I/O tracing setup into parquet/io module
alamb a6a9426
Rework tests
alamb 61f0e9d
Merge remote-tracking branch 'apache/main' into alamb/pr-26897-io-ref…
alamb 1522d2c
test(parquet): complete comment on pruned Bloom filter I/O test
alamb f1517f6
comments
alamb e85a89f
test(parquet): add I/O tracking tests for row group pruning, filter p…
alamb 6b5ec0b
Merge remote-tracking branch 'apache/main' into alamb/parquet-io-prun…
alamb e92655f
Comments
alamb 5da1a02
Update tests
alamb 9a1bfd1
show requests
alamb e04f166
ft
alamb 895173f
prototype: capture parquet I/O through tracing events
adriangb f6270cb
prototype: trace parquet scan stages and render any recorded fields
adriangb 2e64345
prototype: capture traces with one global subscriber
adriangb c659e9c
Merge main into io-tracing-prototype
adriangb File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -43,24 +43,42 @@ async fn test_filter_pushdown_io_disabled() { | |
| // Note: in practice, the default 512 KiB metadata size hint often covers | ||
| // the OffsetIndex and Bloom filters for small files, so they wouldn't | ||
| // need separate requests. | ||
| assert_snapshot!(test.query("SELECT * FROM t WHERE val = 7").await, @r" | ||
| --- Query: SELECT * FROM t WHERE val = 7 (1 rows) --- | ||
| Request 1 | ||
| Head (object size and metadata) | ||
| Request 2 | ||
| Read Parquet footer (offsets 489..1402) | ||
| Request 3 | ||
| Read ColumnIndex and OffsetIndex for columns 'id', 'val' (rg 0, 1, 2) (offsets 286..489) | ||
| Request 4 | ||
| Read dictionary page and data page 0 for column 'id' (rg 0) (offsets 4..51) | ||
| Read dictionary page and data page 0 for column 'val' (rg 0) (offsets 51..98) | ||
| Request 5 | ||
| Read dictionary page and data page 0 for column 'id' (rg 1) (offsets 98..145) | ||
| Read dictionary page and data page 0 for column 'val' (rg 1) (offsets 145..192) | ||
| Request 6 | ||
| Read dictionary page and data page 0 for column 'id' (rg 2) (offsets 192..239) | ||
| Read dictionary page and data page 0 for column 'val' (rg 2) (offsets 239..286) | ||
| Produce batch (1 rows) | ||
| let traces = test.capture_traces(); | ||
| test.query("SELECT * FROM t WHERE val = 7").await.unwrap(); | ||
| assert_snapshot!(traces.render(), @" | ||
| Query (sql=SELECT * FROM t WHERE val = 7, rows=1) | ||
| ObjectStore::head (location=table.parquet) | ||
| Metadata cache miss (cache_enabled=true) | ||
| Prefetch Parquet footer (range=489..1402) | ||
| ObjectStore::get_ranges (location=table.parquet, ranges=1) | ||
| Read byte range (range=489..1402, parquet=footer) | ||
| Read page index (range=286..489) | ||
| ObjectStore::get_ranges (location=table.parquet, ranges=1) | ||
| Read byte range (range=286..489, parquet=ColumnIndex and OffsetIndex for columns 'id', 'val' (rg 0, 1, 2)) | ||
| Open Parquet file (file=table.parquet, size=1402) | ||
| Load Parquet metadata | ||
| Metadata cache hit (has_page_index=true) | ||
| Prune row groups | ||
| Row groups remaining (row_groups=3, row_groups_remaining=3, pruning_predicate=true) | ||
| Load page index | ||
| Load Bloom filters | ||
| Prune row groups with Bloom filters | ||
| Row groups remaining (row_groups_remaining=3) | ||
| Prune pages with page index | ||
| Row groups remaining (row_groups_remaining=3) | ||
| Fetch column chunk data (ranges=2) | ||
| ObjectStore::get_ranges (location=table.parquet, ranges=2) | ||
| Read byte range (range=4..51, parquet=dictionary page and data page 0 for column 'id' (rg 0)) | ||
| Read byte range (range=51..98, parquet=dictionary page and data page 0 for column 'val' (rg 0)) | ||
| Fetch column chunk data (ranges=2) | ||
| ObjectStore::get_ranges (location=table.parquet, ranges=2) | ||
| Read byte range (range=98..145, parquet=dictionary page and data page 0 for column 'id' (rg 1)) | ||
| Read byte range (range=145..192, parquet=dictionary page and data page 0 for column 'val' (rg 1)) | ||
| Fetch column chunk data (ranges=2) | ||
| ObjectStore::get_ranges (location=table.parquet, ranges=2) | ||
| Read byte range (range=192..239, parquet=dictionary page and data page 0 for column 'id' (rg 2)) | ||
| Read byte range (range=239..286, parquet=dictionary page and data page 0 for column 'val' (rg 2)) | ||
| Produce batch (rows=1) | ||
| "); | ||
| } | ||
|
|
||
|
|
@@ -70,24 +88,46 @@ async fn test_filter_pushdown_io_disabled() { | |
| #[tokio::test] | ||
| async fn test_filter_pushdown_io_enabled() { | ||
| 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 | ||
| Head (object size and metadata) | ||
| Request 2 | ||
| Read Parquet footer (offsets 489..1402) | ||
| Request 3 | ||
| Read ColumnIndex and OffsetIndex for columns 'id', 'val' (rg 0, 1, 2) (offsets 286..489) | ||
| Request 4 | ||
| Read dictionary page and data page 0 for column 'val' (rg 0) (offsets 51..98) | ||
| Request 5 | ||
| Read dictionary page and data page 0 for column 'val' (rg 1) (offsets 145..192) | ||
| Request 6 | ||
| Read dictionary page for column 'id' (rg 1) (offsets 98..124) | ||
| Read data page 0 for column 'id' (rg 1) (offsets 124..145) | ||
| Produce batch (1 rows) | ||
| Request 7 | ||
| Read dictionary page and data page 0 for column 'val' (rg 2) (offsets 239..286) | ||
| let traces = test.capture_traces(); | ||
| test.query("SELECT * FROM t WHERE val = 7").await.unwrap(); | ||
| assert_snapshot!(traces.render(), @" | ||
| Query (sql=SELECT * FROM t WHERE val = 7, rows=1) | ||
| ObjectStore::head (location=table.parquet) | ||
| Metadata cache miss (cache_enabled=true) | ||
| Prefetch Parquet footer (range=489..1402) | ||
| ObjectStore::get_ranges (location=table.parquet, ranges=1) | ||
| Read byte range (range=489..1402, parquet=footer) | ||
| Read page index (range=286..489) | ||
| ObjectStore::get_ranges (location=table.parquet, ranges=1) | ||
| Read byte range (range=286..489, parquet=ColumnIndex and OffsetIndex for columns 'id', 'val' (rg 0, 1, 2)) | ||
| Open Parquet file (file=table.parquet, size=1402) | ||
| Load Parquet metadata | ||
| Metadata cache hit (has_page_index=true) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is cool to show the metadata cache hit |
||
| Prune row groups | ||
| Row groups remaining (row_groups=3, row_groups_remaining=3, pruning_predicate=true) | ||
| Load page index | ||
| Load Bloom filters | ||
| Prune row groups with Bloom filters | ||
| Row groups remaining (row_groups_remaining=3) | ||
| Prune pages with page index | ||
| Row groups remaining (row_groups_remaining=3) | ||
| Fetch column chunk data (ranges=1) | ||
| ObjectStore::get_ranges (location=table.parquet, ranges=1) | ||
| Read byte range (range=51..98, parquet=dictionary page and data page 0 for column 'val' (rg 0)) | ||
| Evaluate row filter (predicate=val@0 = 7, rows=3, rows_matched=0) | ||
| Fetch column chunk data (ranges=1) | ||
| ObjectStore::get_ranges (location=table.parquet, ranges=1) | ||
| Read byte range (range=145..192, parquet=dictionary page and data page 0 for column 'val' (rg 1)) | ||
| Evaluate row filter (predicate=val@0 = 7, rows=3, rows_matched=1) | ||
| Fetch column chunk data (ranges=2) | ||
| ObjectStore::get_ranges (location=table.parquet, ranges=2) | ||
| Read byte range (range=98..124, parquet=dictionary page for column 'id' (rg 1)) | ||
| Read byte range (range=124..145, parquet=data page 0 for column 'id' (rg 1)) | ||
| Produce batch (rows=1) | ||
| Fetch column chunk data (ranges=1) | ||
| ObjectStore::get_ranges (location=table.parquet, ranges=1) | ||
| Read byte range (range=239..286, parquet=dictionary page and data page 0 for column 'val' (rg 2)) | ||
| Evaluate row filter (predicate=val@0 = 7, rows=3, rows_matched=0) | ||
| "); | ||
| } | ||
|
|
||
|
|
||
Oops, something went wrong.
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is my biggest hesitation -- to add this new tracing dependency (I know it is just a dev-dependency, but still I feel like it would be easy to accidentally turn into a real dependnecy, and not everyone uses the tracing crate