Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce batched parquet column readers for flat types #14423

Merged
merged 9 commits into from
Nov 20, 2022

Conversation

raunaqmorarka
Copy link
Member

@raunaqmorarka raunaqmorarka commented Oct 1, 2022

Description

FlatDefinitionLevelDecoder implements an optimized decoder for primitive
columns where the definition level is either 0 or 1.
ApacheParquetValueDecoder provides implementations of batched decoders
which are wrappers over existing parquet-mr ValuesReader implementations.
More optimized implementations of ValueDecoder will be added to ValueDecoders
in subsequent chnages.
FilteredRowRangesIterator providers a way to iterate over rows selected by column
index in a batch of positions at a time.
FlatColumnReader makes use of the batched decoders and row-ranges iterator to
implement an optimized ColumnReader with dedicated code paths for nullable and
non-nullable types.
ColumnReaderFactory is updated to use the optimized implementations for
boolean, tinyint, short, int, long, float, double and short decimals.
ColumnReaderFactory falls back to existing implementations where optimized
implementations are not yet available or the flag
parquet.optimized-reader.enabled is disabled.

Non-technical explanation

Improve performance of reading Parquet files for boolean, tinyint, short, int, long, float, double and short decimal data types.

Release notes

( ) This is not user-visible or docs only and no release notes are required.
( ) Release notes are required, please propose a release note for me.
(x) Release notes are required, with the following suggested text:

# Hive, Iceberg, Delta, Hudi
* Improve performance of reading Parquet files for boolean, tinyint, short, int, long, float, double and short decimal data types. The catalog configuration property `parquet.optimized-reader.enabled` can be set to `false` to disable the optimized implementation. ({issue}`14423`)

@raunaqmorarka
Copy link
Member Author

Flat column reader sf1000 partitioned.pdf
Flat column reader sf1000 unpartitioned.pdf
Partitioned : Both TPCH and TPCDS improve by roughly 10%
Unpartitioned : TPCH improves by 10% and TPCDS improves by 20%

@raunaqmorarka raunaqmorarka force-pushed the pqr-flat branch 2 times, most recently from fc6a5db to b1458b7 Compare October 4, 2022 08:41
Copy link
Member

@skrzypo987 skrzypo987 left a comment

Choose a reason for hiding this comment

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

lgtm % It should not count since I co-authored this

Copy link
Member

@sopel39 sopel39 left a comment

Choose a reason for hiding this comment

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

There are test failures.
Would be great to attach benchmark report

@raunaqmorarka
Copy link
Member Author

There are test failures.
Would be great to attach benchmark report

Test failure looks unrelated but I'm re-running to confirm.
Already shared benchmarks in #14423 (comment)

public static void unpack(byte[] values, int offset, long packedValue)
{
values[offset] = (byte) (packedValue & 1);
values[offset + 1] = (byte) ((packedValue >>> 1) & 1);
Copy link
Member

Choose a reason for hiding this comment

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

Are we sure this is better than a loop? What does the resulting assembly and perf look for this? How did we measure it? As in the comment above, the downside is more bytecode and fewer opportunities for inlining as a result.

Copy link
Member

Choose a reason for hiding this comment

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

Those unrollings have show significant improvements in jmh benchmarks and some visible (not huge obviously) gains in macrobenchmarks.

throws Exception
{
benchmark(BenchmarkReadUleb128Int.class)
.withOptions(optionsBuilder -> optionsBuilder.jvmArgsAppend("-Xmx4g", "-Xms4g"))
Copy link
Member

Choose a reason for hiding this comment

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

Why is this needed?

Copy link
Member

Choose a reason for hiding this comment

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

My guess is that this line has been mindlessly copied from one benchmark to another for centuries.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, this is carried over from existing benchmark classes. I was assuming that using a fixed heap size somehow leads to more consistent results, but I don't know if that's actually the case.

raunaqmorarka and others added 3 commits November 19, 2022 11:44
Introduce a standalone ColumnReaderFactory class along with ColumnReader interface

Co-authored-by: Krzysztof Skrzypczynski <krzysztof.skrzypczynski@starburstdata.com>
Krzysztof Skrzypczynski and others added 5 commits November 20, 2022 20:55
NullsDecoder implements an optimized definition levels decoder for primitive
columns where the definition level is either 0 or 1.
ApacheParquetValueDecoders provides implementations of batched decoders
which are wrappers over existing parquet-mr ValuesReader implementations.
More optimized implementations of ValueDecoder will be added to ValueDecoders
in subsequent changes.
FilteredRowRangesIterator providers a way to iterate over rows selected by column
index in a batch of positions at a time.
FlatColumnReader makes use of the batched decoders and row-ranges iterator to
implement an optimized ColumnReader with dedicated code paths for nullable and
non-nullable types.
ColumnReaderFactory is updated to use the optimized implementations for
boolean, tinyint, short, int, long, float, double and short decimals.
ColumnReaderFactory falls back to existing implementations where optimized
implementations are not yet available or the flag
parquet.optimized-reader.enabled is disabled.

Co-authored-by: Raunaq Morarka <raunaqmorarka@gmail.com>
When a large enough number of rows are skipped due to `seek` operation,
it is possible to skip decompressing and decoding parquet pages entirely.
Parquet schema may specify a column definition as OPTIONAL even though
there are no nulls in the actual data. Row-group column statistics
can be used to identify such cases and switch to faster non-nullable read
paths in FlatColumnReader.
@raunaqmorarka raunaqmorarka merged commit e629139 into trinodb:master Nov 20, 2022
@raunaqmorarka raunaqmorarka deleted the pqr-flat branch November 20, 2022 17:22
@github-actions github-actions bot added this to the 404 milestone Nov 20, 2022
@colebow
Copy link
Member

colebow commented Nov 23, 2022

@raunaqmorarka I think we also need to add docs for this to the Hudi connector page. Not urgent, just let me know if you've got that covered or if you'd prefer me to follow up with that.

@raunaqmorarka
Copy link
Member Author

@raunaqmorarka I think we also need to add docs for this to the Hudi connector page. Not urgent, just let me know if you've got that covered or if you'd prefer me to follow up with that.

Right, would be great if you could take care of that.

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

Successfully merging this pull request may close these issues.

6 participants