Skip to content

parquet: Add new PageIndex struct to encapsulate column and offset indexes - #10719

Open
etseidl wants to merge 25 commits into
apache:mainfrom
etseidl:new_page_index
Open

parquet: Add new PageIndex struct to encapsulate column and offset indexes#10719
etseidl wants to merge 25 commits into
apache:mainfrom
etseidl:new_page_index

Conversation

@etseidl

@etseidl etseidl commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Note: this is stacked on #10653

Rationale for this change

Following up on #10653 (review)

If we are going to mess with the APIs I think it may be worth considering some more drastic changes

What changes are included in this PR?

Try to hide some of the complexity of the page indexes behind a struct with accessors for access by row group, or row group and column.

Are these changes tested?

Should be covered by existing

Are there any user-facing changes?

Yes, this changes the public interface to the page indexes quite a bit.

@github-actions github-actions Bot added the parquet Changes to the parquet crate label Aug 17, 2026
@etseidl

etseidl commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

Changes from #10653 can be seen here.

If this looks ok, we can just merge this PR and close the earlier one.

cc @alamb

@etseidl etseidl added the api-change Changes to the arrow API label Aug 17, 2026
Comment thread parquet/src/file/metadata/mod.rs
@alamb

alamb commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Shal I give this one a look?

@etseidl

etseidl commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

Shal I give this one a look?

Yes please. I think there's a todo left and it needs some better docs, but if you could take a look and see if you think this is the direction you wanted to head I'd appreciate it.

@alamb

alamb commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Thank you -- I will do so but probably not until tomorrow (I need a clear mind)

@etseidl
etseidl marked this pull request as ready for review August 19, 2026 18:25

@alamb alamb left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TLDR is I really like this @etseidl and I think it would be great. I am going to test out what it might look like in DataFusion just to gauge the downstream impacts as well

let page_locations = self
.metadata
.page_index()
.map(|i| i.page_locations(rg_idx, self.column_idx).cloned())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this clone is unfortunate (it clones all the page locations into a new Vec) -- I realize it is what the previous code did, but I wonder if there is some way to avoid it

It may also be related to

Where @zhuqi-lucas and others have been looking for a way to load some but not all page indexes (or load them on demand, from a cache, etc).

Maybe it is time to sprinkle on some Arc 🤔

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me see what I can do here...tracing the page_locations down it looks like they are copied once again deep down in the page reader. Might be able to pass a reference here instead.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where @zhuqi-lucas and others have been looking for a way to load some but not all page indexes (or load them on demand, from a cache, etc).

I think the new form will help with that...I envision a builder that starts out with empty vecs sized with num_row_groups and num_columns. Individual cells can then be populated based on what it needed for a given use. We can pop back and forth between page index and page index builder if need be.

&self,
column_page_index: &ParquetColumnIndex,
column_offset_index: &ParquetOffsetIndex,
page_index: &PageIndex,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is looking much nicer

Comment thread parquet/src/file/metadata/mod.rs Outdated
/// # Structure
///
/// Both indexes are organized as a two-level structure:
/// - First level: indexed by row group number

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

(though this might end up being an internal implementation detail that would be better put closer to the field definitions)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed this in a4b7303

/// # use parquet::errors::Result;
///
/// /// Identifies which pages in a column might contain values >= min_value
/// fn find_relevant_pages(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a (very) cool example

self.column_indexes.is_some()
}

/// Returns column indexes for all columns in the specified row group

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these accessors are (so) much easier to read in my mind

/// [`OffsetIndex`]: crate::file::page_index::offset_index::OffsetIndexMetaData
#[derive(Debug, Clone, PartialEq)]
pub struct PageIndex {
column_indexes: Option<Vec<Vec<Option<ColumnIndexMetaData>>>>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the comment above about cloning / handling incremental index loading, we might consider

column_indexes: Option<Vec<Arc<[Option<ColumnIndexMetaData>]>>

So that the indexes could be returned as a &Arc<[Option<ColumnIndexMetaData]> (and thus cheaply cloned) as well as potenitally being able to reuse existing column metadata)

However I am not sure it really matters and don't feel super strongly

@alamb alamb added the next-major-release the PR has API changes and it waiting on the next major version label Aug 19, 2026
@alamb

alamb commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Some findings from a test upgrade

Specifically this commit: apache/datafusion@419027d

This pattern comes up a bunch (to see if the index is "complete" it has to test both column_indexes and offset_indexes.

        metadata
            .page_index()
            .is_some_and(|index| index.has_column_indexes() && index.has_offset_indexes())

Maybe we could add a helper like PageIndex::is_complete that does the check and we could simplify to

        metadata
            .page_index()
            .is_some_and(PageIndex::is_complete)

But otherwise the changes needed are pretty strightforward

@etseidl

etseidl commented Aug 20, 2026

Copy link
Copy Markdown
Contributor Author

Maybe we could add a helper like PageIndex::is_complete that does the check and we could simplify to

That's a good idea...there are a bunch of tests too that do the same thing. I'll get to that first thing tomorrow tonight.

@alamb

alamb commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

😍

@etseidl

etseidl commented Aug 20, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review @alamb. I think this is ready to merge now.

I'm going to get started on the builder to prototype partial population of the indexes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api-change Changes to the arrow API next-major-release the PR has API changes and it waiting on the next major version parquet Changes to the parquet crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Explore changing the form of the Parquet page indexes in ParquetMetaData

2 participants