Repository navigation
importer, mydump: preload small parquet files in a single read - #68250
Conversation
Adds a third parquet reader strategy alongside per-column streaming and per-row-group in-memory preload. When the source file is small enough to fit in memory (default threshold 8 MiB), the parser issues one read for the whole file and reuses that buffer for both footer parsing and every column reader, eliminating the second range GET that the per-row-group path would otherwise issue and absorbing arrow-go's footer seek pattern locally. This is meaningful for jobs that import many small parquet parts where per-file open overhead dominates. The three strategies are dispatched in getBuilder, and the footer reader is selected in newFooterReader so each path is contained. Issue Number: ref pingcap#66180 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Skipping CI for Draft Pull Request. |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThreads an explicit fileSize through Parquet reader construction, selects whole-file in-memory vs streaming readers via prepareReader, records shared preload buffers in ParquetParser for accurate memory estimation, propagates the fileSize to importer callers, and adds tests for whole-file preload behavior. ChangesSmall-file preloading for Parquet parsing
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Hi @joechenrh. Thanks for your PR. PRs from untrusted users cannot be marked as trusted with I understand the commands that are listed here. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
…hold Trim the verbose comments added in the previous commit and use the shorter name in the constant, parser field comment, and tests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Match the smallFileThreshold naming, and remove the debug log in NewParquetParser whose information is already conveyed by the field name and trigger condition. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
@joechenrh I've received your pull request and will start the review. I'll conduct a thorough review covering code quality, potential issues, and implementation details. ⏳ This process typically takes 10-30 minutes depending on the complexity of the changes. ℹ️ Learn more details on Pantheon AI. |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #68250 +/- ##
================================================
- Coverage 76.3266% 74.0123% -2.3144%
================================================
Files 2041 2070 +29
Lines 559579 589653 +30074
================================================
+ Hits 427108 436416 +9308
- Misses 131570 151724 +20154
- Partials 901 1513 +612
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
|
🔍 Starting code review for this PR... |
ingress-bot
left a comment
There was a problem hiding this comment.
This review was generated by AI and should be verified by a human reviewer.
Manual follow-up is recommended before merge.
Summary
- Total findings: 4
- Inline comments: 4
- Summary-only findings (no inline anchor): 0
Findings (highest risk first)
⚠️ [Major] (2)
- Parquet reader memory estimator misses the new whole-file preload mode (pkg/lightning/mydump/parquet_wrapper.go:294, pkg/dxf/importinto/task_executor.go:190, pkg/lightning/mydump/parquet_parser.go:897)
- Small-file parquet path turns reader close failures into hard parse failures (pkg/lightning/mydump/parquet_wrapper.go:300, pkg/lightning/mydump/parquet_parser.go:619)
🟡 [Minor] (2)
ParquetFileMeta.FileSizecomment misstates fallback behavior as always streaming (pkg/lightning/mydump/loader.go:101, pkg/lightning/mydump/parquet_parser.go:427)- Parquet file size contract is duplicated across metadata layers and only partially wired (pkg/lightning/mydump/loader.go:102, pkg/executor/importer/import.go:1747, lightning/pkg/importer/chunk_process.go:111, lightning/pkg/importer/get_pre_info.go:496)
- Make r.Close() non-fatal in newFooterReader's small-file branch so storage close behavior matches the streaming path. - Plumb fileSize through EstimateParquetReaderMemory and account for the whole-file preload buffer via parser.preloadBufferBytes(), so concurrency sizing matches the runtime preload strategy. - Clarify ParquetFileMeta.FileSize comment to only describe the whole-file gate; row-group in-memory preload is unaffected. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
FileSize is a generic source-file property, not a parquet-specific knob, so it does not belong in ParquetFileMeta. Promote it to an explicit parameter of NewParquetParser (and newFooterReader), drop the field from ParquetFileMeta, and update all callers to pass SourceFileMeta.FileSize through directly. This also removes the manual mirror step in newLoadDataParser and lets the lightning openParser / ReadFirstNRowsByFileMeta / sampleDataFromTable paths benefit from the same whole-file preload optimization. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
e2f81ba to
aff6152
Compare
newFooterReader returned the in-memory wrapper and its base separately, even though the wrapper already owned the base. Drop the extra return value, replace ParquetParser.smallFileBase with smallFileWrapper, and let NewParquetParser type-assert the wrapper to detect small-file mode. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The parser only reads .base off the small-file wrapper, so storing the wrapper itself carries phantom pos/fileSize state. Extract base via type-assert in NewParquetParser and keep the field as the bare base pointer. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
prepareReader is what the function actually does: pick the read strategy for one parquet file. Restore the base return so callers do not need a type-assert dance to extract it from the wrapper. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Both branches eventually close r anyway, and r is only needed while NewParquetParser parses the footer. Move the close to a single defer in NewParquetParser so prepareReader stops shipping a thin closer function alongside the reader. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| StartAfter string | ||
| } | ||
|
|
||
| // ReadSeekCloser is the interface that groups the basic Read, Seek and Close methods. |
There was a problem hiding this comment.
Redundant with io.ReadSeekCloser
| } | ||
|
|
||
| // ReadSeekCloser = Reader + Seeker + Closer | ||
| type ReadSeekCloser interface { |
There was a problem hiding this comment.
Redundant with io.ReadSeekCloser
|
/hold |
|
@D3Hunter: Your lgtm message is repeated, so it is ignored. DetailsIn response to this: Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
|
/retest |
|
/cherry-pick release-nextgen-202603 |
|
@D3Hunter: once the present PR merges, I will cherry-pick it on top of release-nextgen-202603 in the new PR and assign it to you. DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the ti-community-infra/tichi repository. |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: D3Hunter, GMHDBJD The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
|
Forget to unhold. |
|
@D3Hunter: new pull request created to branch DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the ti-community-infra/tichi repository. |
What problem does this PR solve?
Issue Number: ref #66180
When
IMPORT INTOingests many small parquet files, each file's footer and row-group data are fetched in separate opens — two for footer parsing inNewParquetParser, then one per row group ingetBuilder→newInMemoryReaderBase. With 1.5k × ~480 KiB parts, the redundant S3 round-trips dominate wall time.What changed and how does it work?
Add a whole-file in-memory strategy alongside the existing per-row-group preload and per-column streaming, and unify their gating under one threshold
inMemoryThreshold(128 MiB).NewParquetParserreads the file once viaprepareReaderwhen it fits, uses the buffer for footer parsing, and letsgetBuilderserve every column from the same buffer. Larger files still fall through to per-row-group preload or streaming.Benchmark
Staging cluster, 1550 × ~480 KiB parquet files on AWS S3, prod-aligned schema. Baseline and PR back-to-back, 1 node × 1 thread.
takeTimep50Gain lands in the inter-chunk gap (parser-open path);
takeTimeand deliver spikes are unaffected, as expected.Check List
Tests
Side effects
Documentation
Release note
Summary by CodeRabbit
Performance Improvements
Tests