GH-48476: [C++] [Parquet] Add max_row_group_size writer property to limit row groups by compressed byte size - #50743
GH-48476: [C++] [Parquet] Add max_row_group_size writer property to limit row groups by compressed byte size#50743zhf999 wants to merge 2 commits into
Conversation
|
Thanks for opening a pull request! This pull request has been automatically converted to a draft because its title doesn't match Arrow's required format. If this is not a minor PR. Could you open an issue for this pull request on GitHub? https://github.com/apache/arrow/issues/new/choose Opening GitHub issues ahead of time contributes to the Openness of the Apache Arrow project. Then could you also rename the pull request title in the following format? or After updating the title, you can mark the pull request as ready for review. See also: |
|
|
|
Related PR: #48468 |
Thanks for contributing! Can you edit the PR desc and ref to the issue, it seems a PR is being referenced here. |
| /// The limit is checked against the compressed pages accumulated in the | ||
| /// current row group, so the actual row group size may slightly exceed it. | ||
| /// Only effective for buffered row groups ( | ||
| /// parquet::arrow::FileWriter::WriteRecordBatch). |
There was a problem hiding this comment.
WriteRecordBatch writes into a buffered row group, which accumulates across calls. That makes the byte size observable between writes, so we can simply stop adding to the current row group once the accumulated compressed size reaches the limit.
While WriteTable uses the non-buffered path, where each call maps to exactly one row group whose row count is fixed up front by the user-supplied chunk_size. Enforcing a byte limit there would require predicting the compressed size before writing, e.g. by estimating an average row size from the previous row group. That's inherently approximate, especially since chunk_size is an explicit contract from the caller.
I wonder if estimation is acceptable in WriteTable?
There was a problem hiding this comment.
IIRC, WriteTable also splits the table into several row groups if max_row_group_length is reached.
There was a problem hiding this comment.
max_row_group_length can be applied there because row counts are known before writing — it just clamps chunk_size. The byte size simply isn't knowable at that point, which is the asymmetry.
|
|
Add max_row_group_size writer property to limit row groups by compressed byte size
GH-#48467 Add configure to limit the row group size
PR Description
Rationale for this change
Currently the Parquet writer only supports limiting row groups by row count
(
WriterProperties::max_row_group_length()). For tables with wide rows orhighly variable row sizes, a row-count limit alone can produce row groups that
are much larger (or smaller) than desired. Many query engines and storage
systems tune around a target row group size in bytes (e.g. HDFS block size),
so it is useful to also support limiting row groups by their compressed byte
size.
What changes are included in this PR?
Add
WriterProperties::max_row_group_size()andWriterProperties::Builder::max_row_group_size(int64_t)to specify the maxrow group size in compressed bytes. The default is unlimited
(
std::numeric_limits<int64_t>::max()), so existing behavior is unchangedunless users opt in.
parquet::arrow::FileWriter::WriteRecordBatchnow checks the size of thecurrent buffered row group before/after each write, counting:
(
RowGroupWriter::total_compressed_bytes_written()),(
RowGroupWriter::total_compressed_bytes()),(
RowGroupWriter::estimated_buffered_stats().dict_bytes, uncompressed).When the accumulated size reaches the limit, a new buffered row group is
started. The check happens at write boundaries, so a row group may exceed
the limit by up to the size of a single written batch.
The limit only applies to buffered row groups (
WriteRecordBatch).WriteTableand the manualNewRowGroup()/WriteColumnChunk()pathscontrol row group boundaries explicitly via
chunk_size/API calls and areintentionally not affected (row counts are fixed before writing in the
non-buffered mode, so the byte size limit cannot be enforced there). This is
documented on the builder method.
Are these changes tested?
Yes.
WriterPropertiesTest.RoundTripThroughBuilder(properties_test.cc) nowcovers
max_row_group_size, with a non-default value added to theoverride_defaultstest case.TestArrowReadWrite.WriteRecordBatchRespectsMaxRowGroupSize(arrow_reader_writer_test.cc) verifies that record batches exceeding the
byte size limit cause row group rollover on subsequent writes.
WriteRecordBatch/WriteTabletests pass unchanged, confirming nobehavior change with the default (unlimited) setting.
Are there any user-facing changes?
Yes, a new opt-in writer property
max_row_group_sizeis added to the publicC++ API (
WriterProperties/WriterProperties::Builder). The default isunlimited, so there is no behavior change for existing users.