feat(parquet): support page index filter for nested column type (paimon side)#409
Closed
zhf999 wants to merge 5 commits into
Closed
feat(parquet): support page index filter for nested column type (paimon side)#409zhf999 wants to merge 5 commits into
zhf999 wants to merge 5 commits into
Conversation
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.
feat: support page index filter for nested column type
Purpose
Linked issue: close #xxx
Previously, page index filtering was only applied to flat (scalar) columns. When the read schema contained any nested field (struct, list, or map), the entire page index filter was disabled as a workaround (
has_nested_fieldcheck inParquetFileBatchReader::SetReadSchema), causing nested columns to fall back to rowgroup-level filtering only and miss fine-grained page-level I/O skipping.This PR extends page index filtering to nested column types by implementing nested array assembly on the Paimon side. The core idea is to read each top-level field (flat or nested) via its leaf
RecordReaders, then manually assemble the nested Arrow array using def/rep levels — mimicking Arrow'sStructReader::BuildArrayandListReader::BuildArraylogic.Key implementation changes:
PageFilteredRowGroupReader: TheReadFilteredRowGroupentry point now acceptsparquet::arrow::FileReader*(instead ofParquetFileReader*) to accessSchemaManifest. Leaf column indices are grouped into top-level fields viaSchemaManifest::GetFieldIndices, and each field is read through the newReadAndAssembleFieldmethod.ReadAndAssembleField(new): Recursively reads a top-level field and assembles the result array:ReadLeafColumn. Top-level leaf columns getdata_page_filter+ compressed ranges for I/O-level page skipping. Leaf columns within nested types skipdata_page_filter(to preserve def/rep level synchronization across sibling leaves) and rely on decode-level skipping only.DefLevelsToBitmap(orDefRepLevelsToBitmapif a repeated descendant exists).DefRepLevelsToList. Map is handled aslist<struct<key, value>>per Parquet's storage model.BuildProjectedField/BuildProjectedSchema(new): Recursively builds a projected Arrow schema fromSchemaFieldtrees, including only requested leaf columns. This enables sub-column projection (e.g., reading onlystruct<x>fromstruct<x, y>).ReadLeafColumn(refactored fromReadFilteredColumn): Returns both theChunkedArrayand theRecordReaderso callers can access def/rep levels for nested array assembly. Theenable_page_filterflag controls whether I/O-level page skipping is applied.FileReaderWrapper: RemovesBuildPageFilteredSchemaandpage_filtered_read_schema_construction logic — schema projection is now delegated toPageFilteredRowGroupReader::BuildProjectedSchema.ParquetFileBatchReader: Removes thehas_nested_fieldcheck that previously disabled page index filter for nested fields.Tests
UT —
PageFilteredRowGroupReaderTest(src/paimon/format/parquet/page_filtered_row_group_reader_test.cpp):NestedStructColumnRowGroupFilter— rowgroup-level filtering on struct columns (fixed expected row count: 50 → 30, since page-level filtering now correctly applies)NestedStructColumnOnlyReadIdField— reading only the flatidfield from a file with nested structNestedListColumnRowGroupFilter— rowgroup-level filtering on list column (fixed expected row count)NestedMapColumnRowGroupFilter— rowgroup-level filtering on map column (fixed expected row count)MultipleAdjacentNestedColumns— multiple adjacent nested columns (fixed expected row count)MultipleNestedColumns(new) — predicate pushdown with all nested types (struct, list, map) and page-level filtering across multiple row groupsNestedStructSubColumnProjection(new) — sub-column projection of a struct type (struct<x>fromstruct<x, y>) with page-level filteringTest helper functions were refactored for reusability:
MakeIdColumn,MakeNestedStructData,MakeListColumnData, andMakeMapColumnDatanow each build a single column (instead of wrapping with anidcolumn), allowing flexible composition across test cases.API and Format
PageFilteredRowGroupReader::ReadFilteredRowGroupsignature changed — now takesparquet::arrow::FileReader*instead ofparquet::ParquetFileReader*. This is an internal API (not ininclude/).FileReaderWrapper::BuildPageFilteredSchemais removed; schema projection is now handled byPageFilteredRowGroupReader::BuildProjectedSchema.include/.Documentation
No new user-facing feature documentation needed — this is an internal performance optimization that is transparent to users.
Generative AI tooling
Generated-by: GLM 5.2