Skip to content

fix: override CachedInputStream::Advance to avoid real I/O for skipped pages#322

Open
zhf999 wants to merge 7 commits into
alibaba:mainfrom
zhf999:arrow-page-patch
Open

fix: override CachedInputStream::Advance to avoid real I/O for skipped pages#322
zhf999 wants to merge 7 commits into
alibaba:mainfrom
zhf999:arrow-page-patch

Conversation

@zhf999
Copy link
Copy Markdown
Contributor

@zhf999 zhf999 commented Jun 1, 2026

Purpose

Linked issue: close #137
This PR depends on #316 and should be merged after that PR is merged.

When page-level filtering skips non-matching pages via data_page_filter,
SerializedPageReader::NextPage() calls stream_->Advance(compressed_len) to
skip the page payload. However, InputStream::Advance() is non-virtual and its
default implementation calls Read() then discards the result. For
CachedInputStream (introduced in #232), this triggers source_->ReadAt() on
cache miss — reading the entire compressed payload of skipped pages from remote
storage, completely defeating the purpose of page-level I/O skipping.

This PR fixes the issue by:

  1. Patching arrow::io::InputStream::Advance() to be virtual, allowing
    subclasses to override it.
  2. Overriding Advance() in CachedInputStream to simply move the stream
    position without any I/O, since the skipped data will never be consumed.

Read() retains its original fallback-to-source behavior on cache miss,
ensuring correctness if a matched page unexpectedly misses the cache.

Tests

Branch query 1 row query 100 rows query 10000 rows
PR#316 16ms 25ms 52ms
This PR 8ms 9ms 42ms

API and Format

  • Adds virtual to arrow::io::InputStream::Advance() declaration in the
    Arrow patch (arrow.diff). No public paimon-cpp API changes.

Documentation

No.

Generative AI tooling

Generated-by: Aone Copilot (Claude 4.7 Opus)

zhf999 added 3 commits May 28, 2026 17:42
…edRowGroupReader::ReadFilteredRowGroup to avoid performance drop on wide tables
Copilot AI review requested due to automatic review settings June 1, 2026 07:28
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR optimizes Parquet page-level filtering by reusing row-group page index metadata across column reads, and adjusts Arrow/Parquet stream behavior to avoid unnecessary I/O when skipping pages.

Changes:

  • Switch ReadFilteredColumn to accept a RowGroupPageIndexReader directly (instead of PageIndexReader) and reuse it across columns in a row group.
  • Cache RowGroupPageIndexReader once per row group to avoid repeated metadata reads.
  • Patch Arrow to allow overriding InputStream::Advance() and implement a no-I/O Advance() for skipped pages.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/paimon/format/parquet/page_filtered_row_group_reader.h Updates the ReadFilteredColumn API to take a row-group page index reader.
src/paimon/format/parquet/page_filtered_row_group_reader.cpp Reuses RowGroupPageIndexReader across column reads and simplifies offset-index lookup.
cmake_modules/arrow.diff Patches Arrow/Parquet to make Advance() virtual and overrides it to skip without triggering reads.
Comments suppressed due to low confidence (1)

cmake_modules/arrow.diff:1

  • The Advance() implementation can move position_ backwards or past bounds when nbytes < 0 or when position_ > length_ (making length_ - position_ negative). This can corrupt stream state. Consider validating nbytes >= 0, clamping using a non-negative remaining byte count (e.g., remaining = std::max<int64_t>(0, length_ - position_)), and returning an error status for invalid inputs or inconsistent internal state.
diff --git a/cpp/src/parquet/arrow/schema.cc b/cpp/src/parquet/arrow/schema.cc

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread cmake_modules/arrow.diff
Comment on lines +428 to +432
/// \brief Advance or skip stream indicated number of bytes
/// \param[in] nbytes the number to move forward
/// \return Status
- Status Advance(int64_t nbytes);
+ virtual Status Advance(int64_t nbytes);
@zhf999 zhf999 requested a review from Copilot June 1, 2026 07:39
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (2)

cmake_modules/arrow.diff:1

  • Making InputStream::Advance() virtual changes the class vtable and is an ABI-breaking change for libarrow consumers. If this repo packages/ships Arrow as a shared library (or links against a system-provided Arrow), this can cause runtime crashes or ODR/ABI mismatches unless all dependents are rebuilt against the same headers and binaries. Prefer an approach that avoids changing the public ABI (e.g., adjust the Parquet skipping logic to use existing APIs such as Seek() where available, or move the optimization into Parquet-specific code that doesn’t require changing arrow::io::InputStream’s virtual surface). If the ABI break is acceptable here, it should be paired with an explicit guarantee that Arrow is always built from this patched source and not mixed with system Arrow.
diff --git a/cpp/src/parquet/arrow/schema.cc b/cpp/src/parquet/arrow/schema.cc

cmake_modules/arrow.diff:1

  • std::min(nbytes, length_ - position_) can move position_ backwards if nbytes is negative, and it can also behave incorrectly if position_ > length_ (since length_ - position_ is negative). This can corrupt subsequent reads/offset calculations. Add an explicit nbytes >= 0 check (returning an error for negative advances), and compute the new position using a saturating/monotonic update (e.g., clamp to [0, length_] without relying on length_ - position_ being non-negative).
diff --git a/cpp/src/parquet/arrow/schema.cc b/cpp/src/parquet/arrow/schema.cc

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.

[Feature] Support page-level bitmap pushdown for parquet format

3 participants