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

Reinitialize the column writers when flushing a row group #10418

Merged
merged 2 commits into from
Feb 1, 2022

Conversation

findinpath
Copy link
Contributor

@findinpath findinpath commented Dec 27, 2021

Reinitialize the column writers when flushing a row group

The previous strategy involved in doing the bugfix was:

In the context of closing a row group, when dealing
with FallbackValuesWriter, it is mandatory to call
the resetDictionary() method only after calling
reset() method.

The field firstPage of the FallbackValuesWriter writer
is then correctly set to true to indicate, in case of
dealing with further pages, that the first page is being
processed.

However, this strategy collides with #5518 (comment) reason why now the column writers get reinitialized from scratch.

Fixes #9749

@cla-bot cla-bot bot added the cla-signed label Dec 27, 2021
@findinpath findinpath force-pushed the bugfix/parquet-9749 branch 3 times, most recently from 3d8d389 to 89667af Compare December 28, 2021 06:50
@@ -164,7 +159,7 @@ private void writeChunk(Page page)
if (bufferedBytes >= writerOption.getMaxRowGroupSize()) {
columnWriters.forEach(ColumnWriter::close);
flush();
columnWriters.forEach(ColumnWriter::reset);
initColumnWriters();
Copy link
Contributor Author

@findinpath findinpath Dec 28, 2021

Choose a reason for hiding this comment

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

This bugfix follows the same strategy as in parquet-mr project:

https://github.com/apache/parquet-mr/blob/master/parquet-hadoop/src/main/java/org/apache/parquet/hadoop/InternalParquetRecordWriter.java#L157-L159

After the row group has been flushed, the column writers get reinitialized from scratch.

The FallbackValuesWriter doesn't reset both of its writers within the #reset() method and this behavior leads to the unwanted behavior documented in #5518 (comment)

One concern which I have with this approach is that the reinitialisation of the writers may affect the performance. I'd need in this regard feedback.

Copy link
Contributor Author

@findinpath findinpath Dec 28, 2021

Choose a reason for hiding this comment

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

Comparing https://github.com/trinodb/trino/runs/4650149952?check_suite_focus=true (a test run of this branch) and
https://github.com/trinodb/trino/runs/4649720577?check_suite_focus=true (a build on master) on TestFullParquetReader i see differences of about 20% in favor of the master implementation compared to the current bugfix implementation (for thetrino-hive, trino-parquet tests).

I ran again the tests https://github.com/trinodb/trino/runs/4652707273?check_suite_focus=true and found out no major difference between the runs. Actually in most of the cases, the tests were running faster on the branch bugfix/parquet-9749 than on master

The test TestFullParquetReader.testNestedStructs took 1m / 2m on the bugfix branch and 8 seconds on master. I'm not sure whether this is relevant or is it linked to the github build runner.

Copy link
Member

Choose a reason for hiding this comment

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

The FallbackValuesWriter doesn't reset both of its writers within the #reset() method and this behavior leads to the unwanted behavior documented in #5518 (comment)

When does the FallbackValuesWriter get used?

One concern which I have with this approach is that the reinitialisation of the writers may affect the performance. I'd need in this regard feedback.

That should not be much of a problem. It happens once per row group and it doesn't seem to be a very expensive operation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When does the FallbackValuesWriter get used?

It gets used as a fallback for the situation where the dictionary encoding grows too big.

https://github.com/apache/parquet-format/blob/master/Encodings.md#dictionary-encoding-plain_dictionary--2-and-rle_dictionary--8

@findinpath findinpath changed the title Reset the dictionary after resetting the value writer Reinitialize the column writers when flushing a row group Dec 28, 2021
@findepi findepi requested review from martint and raunaqmorarka and removed request for findepi January 4, 2022 09:19
@findinpath findinpath force-pushed the bugfix/parquet-9749 branch from 23bf3a8 to e1b6c09 Compare January 4, 2022 10:10
@alexjo2144
Copy link
Member

What about changing the top three reset calls to re-initialize here https://github.com/trinodb/trino/blob/master/lib/trino-parquet/src/main/java/io/trino/parquet/writer/PrimitiveColumnWriter.java#L313

The rest of the fields should reset/clear fine, it's just the ValueWriters that seem to have a problem.

If that's not worth it, I think the reset method is unused and can be removed.

@findinpath
Copy link
Contributor Author

What about changing the top three reset calls to re-initialize here https://github.com/trinodb/trino/blob/master/lib/trino-parquet/src/main/java/io/trino/parquet/writer/PrimitiveColumnWriter.java#L313

@alexjo2144 I'm not sure that I follow what you mean.
The PrimitiveColumnWriter doesn't have any knowledge on how to re-initialize/reinstantiate the underlying writers.

https://github.com/trinodb/trino/blob/master/lib/trino-parquet/src/main/java/io/trino/parquet/writer/PrimitiveColumnWriter.java#L100-L102

@alexjo2144
Copy link
Member

Sorry, my thought was can we either:

  1. Change the fields of PrimitiveColumnWriter so that it has what it needs to re-initialize the underlying writers to minimize the number of objects thrown out on each row group

or if not

  1. Remove ColumnWriter#reset, since I think you're removing the one place it was used

@findinpath findinpath force-pushed the bugfix/parquet-9749 branch from e1b6c09 to 682eb69 Compare January 7, 2022 14:55
@findinpath
Copy link
Contributor Author

findinpath commented Jan 7, 2022

Remove ColumnWriter#reset, since I think you're removing the one place it was used

@alexjo2144 Indeed, this method is now no longer needed.

I'm still investigating also the refactoring possibility:

Change the fields of PrimitiveColumnWriter so that it has what it needs to re-initialize the underlying writers to minimize the number of objects thrown out on each row group

Taken from the Parquet documentation https://parquet.apache.org/documentation/latest/

We recommend large row groups (512MB - 1GB). Since an entire row group might need to be read, we want it to completely fit on one HDFS block.

I'm thinking that in such cases there is no really a big overhead of creating again from scratch the writers in case of dealing with a new row group.

@findinpath findinpath requested a review from findepi January 10, 2022 06:28
@findepi findepi removed their request for review January 10, 2022 08:28
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.

This looks ok.
However, my knowledge about writing Parquet files is non-existent so I can't be the one to approve anything here.

@findepi
Copy link
Member

findepi commented Jan 28, 2022

Thanks @skrzypo987 for taking a look

@findepi findepi merged commit 53cb7b5 into trinodb:master Feb 1, 2022
@findepi findepi mentioned this pull request Feb 1, 2022
@github-actions github-actions bot added this to the 370 milestone Feb 1, 2022
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.

Iceberg failure when reading Parquet file written by Iceberg connector: Dictionary is missing for Page
5 participants