Skip to content

GH-51684: [C++][Parquet] Keep the CDC chunking state across row groups - #51685

Open
kszucs wants to merge 6 commits into
apache:mainfrom
kszucs:cdc-row-group-reset
Open

kszucs wants to merge 6 commits into
apache:mainfrom
kszucs:cdc-row-group-reset

Conversation

@kszucs

@kszucs kszucs commented Oct 2, 2026 •

Copy link
Copy Markdown
Member

Rationale for this change

The content-defined chunker was owned by the column writer, which is recreated for every row group, so the chunking state was reset at each row group boundary. See #51684.

What changes are included in this PR?

The file writer creates one chunker per leaf column and passes it to the column writers of every row group through a new ColumnWriter::Make() argument.

Are these changes tested?

Yes. IndependentOfRowGroupBoundaries writes the same table into one and into six row groups and expects the same page boundaries apart from the row group ends. The first commit adds it alone, failing without the fix.

Are there any user-facing changes?

Deduplication results

A 1 GiB file of 128Mi random int64 values (PLAIN, snappy, default CDC options) compared with a copy that has 10 rows inserted at 20%. The ratio is the share of bytes left after deduplicating both files with the Xet chunker; 50% means the edited copy adds almost nothing.

Row groups pyarrow 25.0.1 This PR arrow-rs 58.4
8 × 16Mi rows 50.2% 50.1% 50.1%
32 × 4Mi rows 50.6% 50.4% 50.5%
128 × 1Mi rows 52.4% 51.6% 51.6%
512 × 256Ki rows 59.8% 56.4% 56.5%
2048 × 64Ki rows 84.8% 74.2% 74.2%
ParquetWriter.write() per 100k rows 75.2% 66.7% 64.3%*
Without CDC 86.3% 86.3% 86.3%

* arrow-rs doesn't start a row group per write call, so it writes 8 row groups where pyarrow writes 1343.

The page boundaries now match arrow-rs, which already keeps the chunker state across row groups.

Was AI used for this PR?

In accordance to the AI generation guidelines, please disclose below whether and how AI was used in this PR.

Claude Code wrote the code, tests and description under human direction.

PR code and description written by:

  • Human
  • AI

Reviewed before submission by:

  • Human
  • AI
  • Not reviewed

🤖 Generated with Claude Code

@kszucs
kszucs force-pushed the cdc-row-group-reset branch 5 times, most recently from ed7b88a to 10d98d8 Compare October 2, 2026 10:14
@kszucs
kszucs marked this pull request as ready for review October 2, 2026 10:31
Copilot AI balanced review requested due to automatic review settings October 2, 2026 10:31

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

The changed public factory breaks ABI and disables CDC for existing direct callers.

Review effort: Balanced
Findings: 1 High severity

Open (1)
What changed in this PR

Persists Parquet content-defined chunking state across row groups.

Changes:

  • Moves chunker ownership to the file writer.
  • Passes chunkers into successive column writers.
  • Adds row-group boundary independence coverage.
File Description
cpp/​src/​parquet/​file_writer.cc Manages per-column chunkers.
cpp/​src/​parquet/​column_writer.h Extends the column-writer factory.
cpp/​src/​parquet/​column_writer.cc Uses externally managed chunkers.
cpp/​src/​parquet/​chunker_internal.h Updates ownership documentation.
cpp/​src/​parquet/​chunker_internal.cc Stores level metadata by value.
cpp/​src/​parquet/​chunker_internal_test.cc Tests stable page boundaries.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread cpp/src/parquet/column_writer.h Outdated
@kszucs
kszucs force-pushed the cdc-row-group-reset branch from 10d98d8 to 8d016a7 Compare October 2, 2026 13:54
Copilot AI balanced review requested due to automatic review settings October 2, 2026 13:54

This comment was marked as duplicate.

Copilot AI balanced review requested due to automatic review settings October 2, 2026 15:29
@kszucs
kszucs force-pushed the cdc-row-group-reset branch from 8d016a7 to f556bae Compare October 2, 2026 15:29

This comment was marked as duplicate.

Copilot AI balanced review requested due to automatic review settings October 2, 2026 16:35
@kszucs
kszucs force-pushed the cdc-row-group-reset branch from f556bae to 0a0f214 Compare October 2, 2026 16:35

This comment was marked as duplicate.

Copilot AI balanced review requested due to automatic review settings October 2, 2026 16:38
@kszucs
kszucs force-pushed the cdc-row-group-reset branch from 0a0f214 to 0e77f38 Compare October 2, 2026 16:38
Comment thread cpp/src/parquet/column_writer.h Outdated
Comment thread cpp/src/parquet/column_writer.cc Outdated
Comment thread cpp/src/parquet/file_writer.cc Outdated
Comment thread cpp/src/parquet/file_writer.cc Outdated
@github-actions github-actions Bot added awaiting changes Awaiting changes and removed awaiting merge Awaiting merge labels Oct 10, 2026
Copilot AI balanced review requested due to automatic review settings October 10, 2026 18:00
@github-actions github-actions Bot added awaiting change review Awaiting change review and removed awaiting changes Awaiting changes labels Oct 10, 2026
@github-actions github-actions Bot added awaiting changes Awaiting changes and removed awaiting change review Awaiting change review labels Oct 10, 2026

Copilot AI 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.

🔵 Needs a closer look

The new public factory rejection behavior lacks direct regression coverage.

1 open finding
1 resolved since last review
Previously missed (1)

In code that hasn't changed since last review

Low severity Add regression test for CDC-enabled ColumnWriter::Make failure

cpp/​src/​parquet/​column_writer.cc:784

The new public-factory failure path is not covered: the added row-group test only writes through ParquetFileWriter. Add a regression test that calls the existing four-argument ColumnWriter::Make with CDC-enabled properties and asserts this ParquetException, so this intentional public API behavior cannot silently change.

🧠 Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 10, 2026 18:06
@github-actions github-actions Bot added awaiting change review Awaiting change review and removed awaiting changes Awaiting changes labels Oct 10, 2026
The column writer owns the content defined chunker and is recreated for every
row group, so the chunking state is reset at each row group boundary. Writing
the same table into one and into multiple row groups must give the same page
boundaries apart from the row group ends.
The column writer created the chunker for every column chunk, so the chunking
state was reset at each row group. The file writer now keeps one chunker per
leaf column and passes it to the column writers of all the row groups.
The chunker stores the level information by value, so the file writer doesn't
need to share it with the column writers. Computing it is cheap.
… previous column

The column ordinal and the column metadata fall out of step if closing the
previous column writer throws and NextColumn() is called again, but that isn't
specific to content defined chunking.
…lumnWriter::Make()

The column writer throws if content defined chunking is enabled without a
chunker, so a separate private overload isn't needed.
@kszucs
kszucs force-pushed the cdc-row-group-reset branch from f20c5f0 to 77b9299 Compare October 10, 2026 18:09
@github-actions github-actions Bot added awaiting changes Awaiting changes awaiting change review Awaiting change review and removed awaiting change review Awaiting change review awaiting changes Awaiting changes labels Oct 10, 2026

Copilot AI 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.

🔵 Needs a closer look

The exported ColumnWriter::Make change still breaks ABI compatibility and existing CDC callers.

1 open finding

🧠 Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 10, 2026 18:09
Drop ContentDefinedChunker::Make() and the move assignment operator, the file
writer only needs the move constructor to keep the chunkers in a vector.

Copilot AI 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.

🟡 Changes recommended

The exported ColumnWriter::Make change still breaks API/ABI compatibility.

2 open findings

🧠 Review effort: Balanced

Comment on lines +134 to +137
static std::shared_ptr<ColumnWriter> Make(
ColumnChunkMetaDataBuilder*, std::unique_ptr<PageWriter>,
const WriterProperties* properties, BloomFilter* bloom_filter = NULLPTR,
internal::ContentDefinedChunker* content_defined_chunker = NULLPTR);
@kszucs

kszucs commented Oct 10, 2026

Copy link
Copy Markdown
Member Author

Thanks @wgtmac for reviewing! I addressed the issues, ready for another look.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants