Skip to content

Further refactor Parquet readers for v2 support#13290

Merged
RussellSpitzer merged 7 commits into
apache:mainfrom
eric-maynard:parquet-v2-refactor
Jun 25, 2025
Merged

Further refactor Parquet readers for v2 support#13290
RussellSpitzer merged 7 commits into
apache:mainfrom
eric-maynard:parquet-v2-refactor

Conversation

@eric-maynard

@eric-maynard eric-maynard commented Jun 10, 2025

Copy link
Copy Markdown
Contributor

In issues like #7162 and #11371, it's reported that newer Parquet encodings like DELTA_BINARY_PACKED don't work with the current Parquet readers. #11661 recently refactored the Parquet readers to improve code re-use, but there a few more changes needed to prepare us for Parquet v2 support.

This refactor introduces a new interface VectorizedValuesReader and changes readers like TimestampMillisReader to work with this new type. After this change, new implementations of VectorizedValuesReader can be added to support encodings like DELTA_BINARY_PACKED.


This PR is a revival of @wgtmac's #9772, which based on our conversion he will not be able to continue work on. Thanks for the great work, @wgtmac.

@github-actions github-actions Bot added the arrow label Jun 10, 2025
@Override
protected void initDataReader(Encoding dataEncoding, ByteBufferInputStream in, int valueCount) {
ValuesReader previousReader = plainValuesReader;
ValuesReader previousReader = (ValuesReader) valuesReader;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Explicit cast?

@eric-maynard eric-maynard Jun 18, 2025

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.

Yeah currently we need the cast due to a bit of a Java-based pickle, happy to change this up if you have any ideas on how it can be improved.

  • VectorizedValuesReader is currently not bound to ValuesReader. We can't just make VectorizedValuesReader extend ValuesReader because the former is an interface and the latter is a class.
  • We can't just make VectorizedValuesReader an ABC because then classes like VectorizedPlainValuesReader can't extend both it and PlainValuesReader.
  • Since ValuesReader is an ABC in Parquet but VectorizedValuesReader is an interface, we can't easily mark valuesReader as being both types.
    • We could create a generic method and bind the type to <T extends ValuesReader & VectorizedValuesReader> but that feels clunky

I see a couple of ways out of this but they mostly involve copying a lot of code and I thought this cast wasn't too high of a price to pay. It does mean that we need to more or less keep VectorizedValuesReader in sync with ValuesReader if it evolves.

(This cast is inherited from #9772)

import org.apache.parquet.io.api.Binary;

/** Interface for value decoding that supports vectorized (aka batched) decoding. */
interface VectorizedValuesReader {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In the Spark corresponding class there are some other methods available, do we need those as well? Part of a followup or un-needed?

https://github.com/apache/spark/blob/master/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/VectorizedValuesReader.java#L31-L72

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.

A Spark expert can correct me, but I think the read methods with a WritableColumnVector parameter are for copying the data into a Spark WritableColumnVector. In Iceberg we use Arrow vectors instead of WritableColumnVectors. The skip methods are for Parquet page skipping. For the v2 read support, they are not needed. I'd like to resurrect my work on Parquet page skipping, so I may look into leveraging those skip methods myself, but for now, we don't need them.

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.

Yeah that's exactly correct. I played with the idea of implementing something like WritableColumnVector within Iceberg (but for building something like a VectorizedColumnIterator), but I think we won't need all of that code after all.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks @wypoon and @eric-maynard, that all sounds good to me

@RussellSpitzer

Copy link
Copy Markdown
Member

I have some small questions about the Roadmap for where we go from here but this makes sense to me as a first step. As long as we are more or less copying the Spark approach I think we are probably safe here. @huaxingao Could you do a quick check as well?

@RussellSpitzer

Copy link
Copy Markdown
Member

Some weird rebase happened here, git history looks scary now :)

@eric-maynard eric-maynard force-pushed the parquet-v2-refactor branch from a63ee5d to 9ecc2be Compare June 18, 2025 16:49
@huaxingao

Copy link
Copy Markdown
Contributor

@eric-maynard Thanks for the PR! The approach looks good to me and seems like a reasonable first step.

@eric-maynard eric-maynard requested a review from huaxingao June 23, 2025 17:15
@eric-maynard

Copy link
Copy Markdown
Contributor Author

Thanks @huaxingao! I've added Javadocs

About the scary diff @RussellSpitzer, it should be fixed but unfortunately I can't remove the tags which got auto-added when the diff was artificially massive

@RussellSpitzer

Copy link
Copy Markdown
Member

@huaxingao and @wypoon do y'all have any other comment on this pr?

@huaxingao huaxingao 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.

LGTM

@wypoon wypoon 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.

LGTM too.

@RussellSpitzer RussellSpitzer merged commit 4213a50 into apache:main Jun 25, 2025
39 checks passed
@RussellSpitzer

Copy link
Copy Markdown
Member

Merged, Thanks @eric-maynard for the pr, and @huaxingao and @wypoon for reviewing.

@RussellSpitzer

Copy link
Copy Markdown
Member

Also thanks @wgtmac for starting this!


class VectorizedPlainValuesReader extends ValuesAsBytesReader implements VectorizedValuesReader {

public static final int INT_SIZE = 4;

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.

do these need to be public? They don't seem to be used anywhere outside of this class

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.

They’re used in the follow up PR (though currently they could be protected), but they could have been private in this PR. Good catch

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

Labels

arrow core docs flink spark Specification Issues that may introduce spec changes.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants