Skip to content

GH-3344: Adaptive compression for v2 page#3368

Open
ConeyLiu wants to merge 5 commits into
apache:masterfrom
ConeyLiu:compress-or-not
Open

GH-3344: Adaptive compression for v2 page#3368
ConeyLiu wants to merge 5 commits into
apache:masterfrom
ConeyLiu:compress-or-not

Conversation

@ConeyLiu

@ConeyLiu ConeyLiu commented Dec 8, 2025

Copy link
Copy Markdown
Contributor

Rationale for this change

Closes #3344

What changes are included in this PR?

Are these changes tested?

Yes, added UT.

Are there any user-facing changes?

Yes, add new configuration. No breaking changes.

@ConeyLiu

ConeyLiu commented Dec 8, 2025

Copy link
Copy Markdown
Contributor Author

cc @pitrou @alamb @mapleFU

definitionLevels,
data,
statistics,
10);

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.

It does not make sense to have a threshold greater than 1.0, does it?
In any case, the data of a column full of zeros is extremely compressible (you might want to disable dictionary encoding?), so the default value should work IMHO.

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.

Changed to 1.0

assertEquals(
"Data should be stored uncompressed when compression ratio exceeds threshold",
uncompressedSize,
compressedSize);

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.

Perhaps you want to read the data back and check it's as expected?

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.

Added

* @param threshold the compression ratio threshold, default is {@value #DEFAULT_V2_PAGE_COMPRESS_THRESHOLD}
* @return this builder for method chaining
*/
public Builder withV2PageCompressThreshold(double threshold) {

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.

I'm not sure it makes sense to put "V2" in the API name? For users it doesn't seem be relevant (just keep it mentioned in the docstrings).

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.

Good point, updated

@pitrou

pitrou commented Dec 8, 2025

Copy link
Copy Markdown
Member

I'll let Java experts review this @Fokko @wgtmac

converter.getEncoding(headerV2.getEncoding()),
BytesInput.from(pageLoad),
headerV2.is_compressed,
compressed,

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.

Fixed a potential bug

public static final boolean DEFAULT_SIZE_STATISTICS_ENABLED = true;

public static final boolean DEFAULT_PAGE_WRITE_CHECKSUM_ENABLED = true;
public static final double DEFAULT_PAGE_COMPRESS_THRESHOLD = 0.98;

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.

Why is this magic number? Is it better to use a smaller number like 0.9 or 0.85?

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.

Per the suggestion linked here: #3344 (comment)

}
}

public static Builder build(BytesInputCompressor compressor, MessageType schema, ByteBufferAllocator allocator) {

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.

Is it better to use a separate issue to implement this, though I'm fine to keep it as is.

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.

Now, the ColumnChunkPageWriteStore implements a similar builder pattern. Just add a new option method.

@github-actions

Copy link
Copy Markdown

This pull request has been automatically marked as stale because it has had no activity for at least 2 months. If you are still working on this change or plan to move it forward, please leave a comment or push a new commit so we know to keep it open. Otherwise, this PR will be closed automatically in about one month. Thank you for your contribution to Apache Parquet!

@ConeyLiu

Copy link
Copy Markdown
Contributor Author

Sorry this PR hasn’t been updated for so long due to work. Please review it when you get a chance. @wgtmac

compressed = true;
double compressionRatio = (double) compressedData.size() / data.size();
if (compressor.getCodecName() != CompressionCodecName.UNCOMPRESSED
&& compressionRatio > pageCompressThreshold) {

@wgtmac wgtmac Jul 15, 2026

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.

This fallback can break for one-shot BytesInput implementations. compressor.compress(data) may consume data (for example stream-backed input), and then the fallback assigns the already-consumed input back to compressedData for CRC/writing. Please materialize/copy the original page bytes before compression, or otherwise make the fallback use a replayable copy. (Reviewed by Codex)

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.

Materialized data before compression.

* @param threshold the compression ratio threshold, default is {@value #DEFAULT_PAGE_COMPRESS_THRESHOLD}
* @return this builder for method chaining
*/
public Builder withPageCompressThreshold(double threshold) {

@wgtmac wgtmac Jul 15, 2026

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.

Please validate the threshold or document the allowed range here. As written, values like NaN, negative numbers, or 100 are accepted even though the API describes this as a compressed/uncompressed ratio threshold. I would either enforce a finite range (for example 0.0 <= threshold <= 1.0) or explicitly document the special meanings of out-of-range values. (Reviewed by Codex)

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.

Added validation

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make compression adaptive with V2 data pages

3 participants