Skip to content

GH-3952: Read each page header only once in the CLI pages command - #3953

Open
PDGGK wants to merge 1 commit into
apache:masterfrom
PDGGK:cli-pages-read-headers-once
Open

PDGGK wants to merge 1 commit into
apache:masterfrom
PDGGK:cli-pages-read-headers-once

Conversation

@PDGGK

@PDGGK PDGGK commented Nov 13, 2026

Copy link
Copy Markdown

Rationale for this change

parquet pages takes time quadratic in the number of pages in a column chunk. Since #3326 the size printed for a page comes from its page header, and getPageCompressedSize() finds that header by opening a new stream on the file and reading the headers of the column chunk from its start up to the current page. A chunk with N pages costs N stream opens and N(N+1)/2 header reads. On a file with 8,000 pages per column chunk the command took 41.6 s, where parquet pages --raw took 0.8 s.

What changes are included in this PR?

The command opens one stream next to the reader and keeps it for the whole run. The formatter reads the headers of the current column chunk once, in order, continuing from the last header it read as the pages are formatted, and starts again at the next column chunk. The sizes come from the same headers as before, so the output does not change.

Are these changes tested?

testReadsEachPageHeaderOnce writes a file with more than one row group, two columns and 10 rows per page, runs the command through a local file system registered under its own scheme, and compares every printed size with the page headers. It then checks that the command read less than three times the file length from that file system. On master it fails with Expecting actual: 611298L to be less than: 58965L. With the change the command read 17,378 bytes of the 19,655-byte file. The size comparison alone passes on master too, since the output is the same.

mvn -pl parquet-cli verify passes: 90 tests (2 skipped, as on master), spotless, rat and japicmp. I skipped javadoc there.

I also timed parquet pages <file> with parquet-cli built from master and from this branch, on files with one row group, two columns (int64, int32) and 100 rows per page, JDK 17 in a Linux container:

pages per column chunk master this branch --raw (master)
1,000 1.5 s 0.5 s 0.7 s
2,000 3.2 s 0.7 s 0.6 s
4,000 10.9 s 0.6 s 0.6 s
8,000 41.6 s 0.7 s 0.8 s

On all four files the output of the two builds is byte for byte the same (same MD5).

I did not run it on encrypted files or on a remote file system. The headers read are the same as before, so I expect no difference there, but that is not tested.

Are there any user-facing changes?

No change in output. parquet pages is faster on column chunks with many pages.

Closes #3952

ShowPagesCommand looked up the compressed size of every page by opening
a new stream on the file and reading the page headers of the column
chunk from its start up to that page. A column chunk with N pages
therefore cost N stream opens and N(N+1)/2 header reads, so the command
slowed down quadratically with the number of pages per column chunk.

Keep one stream open for the command and read the headers of the
current column chunk once, in order, as its pages are formatted. The
printed sizes are unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

parquet pages takes time quadratic in the number of pages per column chunk

1 participant