feat(reader): support late materialization with probe/payload two-phase reads - #243
Merged
Conversation
gripleaf
reviewed
Aug 24, 2026
zhf999
marked this pull request as ready for review
August 25, 2026 10:24
lxy-9602
reviewed
Aug 26, 2026
lxy-9602
reviewed
Aug 26, 2026
gripleaf
reviewed
Aug 26, 2026
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
This PR is inspired by #196, thanks @gripleaf for the initial work.
Purpose
This PR introduces a late-materializing file batch reader (
LateMaterializingFileBatchReader)that performs probe/payload two-phase reads when a predicate is pushed down through
SetReadSchema. Without a predicate the reader degrades to a plain passthrough, so it is safe toinstall unconditionally.
Motivation. In a standard read, all projected columns are materialized together, even though a
pushed-down predicate may filter out the vast majority of rows. Late materialization splits the
read into two passes:
build a
matched_bitmap_of surviving rows.then assemble the probe and payload columns into a single struct array in
full_schema_fieldorder.
This avoids decoding and holding the wide payload columns for rows that will be discarded.
Architecture. The reader is installed below the prefetch layer by wrapping the
format-specific
ReaderBuilderwith aLateMaterializingReaderBuilder(
AbstractSplitRead::CreateFileBatchReader). Each parallel reader under the prefetch layer thusgets its own late-materializing wrapper. The reader implements the full
PrefetchFileBatchReaderinterface, forwarding schema, row-count, seek, read-range, and metricqueries to the inner reader while interposing the two-phase logic in
SetReadSchema/NextBatch.The feature is controlled by
ReadContextBuilder::EnableLateMaterializing(bool)(defaultfalse).When disabled, no wrapping occurs and the read path is unchanged.
TODOs
Key files:
src/paimon/common/reader/late_materializing_file_batch_reader.{h,cpp}— core reader with astate machine (
kInit → kProbing → kRunning | kNoLatMat → kEOF), probe data filtering, payloadbatch reading with bitmap compaction, and full-batch assembly.
src/paimon/common/reader/late_materializing_reader_builder.h—ReaderBuilderwrapper thatinstalls the late-materializing reader around each format reader produced by the inner builder.
src/paimon/core/operation/abstract_split_read.{h,cpp}— integration: the reader builder iswrapped with
LateMaterializingReaderBuilderinsideCreateFileBatchReader.src/paimon/format/parquet/parquet_file_batch_reader.{h,cpp}— fixed read-range loss afterreentrant
SetReadSchemaby caching and re-applying read ranges.src/paimon/common/utils/arrow/arrow_utils.{h,cpp}— addedArrowUtils::NormalizeArrayOffsets()helper for post-slice Arrow array offset normalization.
src/paimon/testing/mock/mock_file_batch_reader.h— enhanced to faithfully emulate a realformat reader:
SetReadSchemanow resets position and read ranges;NextBatchWithBitmaphonours assigned read ranges; a
ProjectBatchhelper supports column re-selection.src/paimon/CMakeLists.txt— registers the new source and test files.Safety guards:
SetReadSchemareturns
Status::Invalidto surface the configuration error early.SetReadSchemahas not been called beforeNextBatch, the reader transitions directly tokNoLatMat, matching theFileBatchReadercontract for schema-less reads.Tests
Unit tests. A dedicated test suite
LateMaterializingFileBatchReaderTestis added insrc/paimon/common/reader/late_materializing_file_batch_reader_test.cpp(16 cases):PassThroughWhenNoPredicatePassThroughWhenPayloadEmptyContiguousSubsetAcrossBatchesScatteredAlternatingMatchMatchedIntersectsSelectionselection_bitmapEmptyMatchReturnsEofSeekToRowRealignsProbeCursorSeekToRowrealigns the probe cursor and stateReadRangesForwardedAcrossPhasesReentrantSetReadSchemaSetReadSchemaresets state cleanlyForwardsRowCountAndFileSchemaGetNumberOfRows/GetFileSchemaforwardedMultiFieldPreservesColumnOrderNestedPayloadColumnFailsOnPredicateTypeMismatchWorksAsInnerOfPrefetchReaderPrefetchFileBatchReaderImplPrefetchInnerReentrantSetReadSchemaSetReadSchemaunder prefetchPrefetchInnerParallelReadersWithSeekIntegration tests:
test/inte/read_inte_test.cpp— new LM-enabled read tests with and without predicates.test/inte/scan_and_read_inte_test.cpp— new LM-enabled scan-and-read tests.test/inte/read_inte_with_index_test.cpp—TestBitmapIndexWithLateMaterializing.src/paimon/core/operation/merge_file_split_read_test.cpp—TestReadWithPredicateAndLateMaterializing.EnableLateMaterializing(false).Known Limitations / TODOs
SetReadRangesis a no-op — the ORC reader currently ignores read ranges and alwaysreads the entire file, causing read amplification in the payload pass.
PrefetchFileBatchReaderonly pre-buffers probe columns — the prefetch layer currentlyissues
PreBufferRangeonly for the probe schema; payload columns are read synchronously ondemand without pre-buffering.
PredicateFilter::Test; a future optimization will switch toarrow::compute::Filterwhichsupports SIMD-accelerated batch filtering.
API and Format
No storage format or protocol change.
Public API changes (
include/paimon/):PrefetchFileBatchReader::GetNextRowToRead()— return type changed fromuint64_ttoResult<uint64_t>to propagate errors from seek operations. All implementors updated(Parquet, ORC, PrefetchImpl, LateMat).
ReadContext— addedEnableLateMaterializing() constgetter andReadContextBuilder::EnableLateMaterializing(bool)builder method (default:false).Internal signature changes in the split-read path:
AbstractSplitRead::CreateFileBatchReader—const ReaderBuilder*→std::unique_ptr<ReaderBuilder>(ownership transfer to allow wrapping).AbstractSplitRead::CreateFieldMappingReader— same change for thereader_builderparameter.Both are private methods of
AbstractSplitRead; all call sites within the class are updated in thesame change.
Documentation
No user-facing documentation change yet. User-facing documentation for the late-materialization
read mode will be added in a follow-up once the feature stabilizes.
Generative AI tooling
Generated-by: Qoder