Skip to content

feat: add read-optimized system table#403

Open
gripleaf wants to merge 3 commits into
alibaba:mainfrom
gripleaf:feat/value_stats_filter
Open

feat: add read-optimized system table#403
gripleaf wants to merge 3 commits into
alibaba:mainfrom
gripleaf:feat/value_stats_filter

Conversation

@gripleaf

@gripleaf gripleaf commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Purpose

Add support for the read-optimized $ro system table. For primary-key tables, $ro reads only the highest LSM level produced by full compaction and skips merge-on-read across levels. Append-only tables keep the same read behavior as the base table, including streaming reads.

This also refactors read-optimized scan configuration into DataTableBatchScan, uses context builders for $ro scan/read contexts, and documents freshness and value-stats filtering behavior.

Tests

E2E test:

  • SystemTableTest.TestReadOptimizedSystemTableRegistration
  • SystemTableTest.TestReadOptimizedSystemTablePathParsing
  • TableScanTest.TestReadOptimizedPrimaryKeyStreamingScanUnsupported
  • SystemTableReadInteTest.TestReadOptimizedSystemTable
  • SystemTableReadInteTest.TestReadOptimizedAppendOnlySystemTableWithStreamingScan
  • SystemTableReadInteTest.TestReadOptimizedSystemTableWithBranch
  • SystemTableReadInteTest.TestReadOptimizedSystemTableWithFirstRowMergeEngine

API and Format

No public API, storage format, or protocol changes.

Documentation

Added user guide documentation for system tables and the read-optimized $ro system table.

Generative AI tooling

Generated-by: OpenAI Codex GPT-5

@gripleaf gripleaf force-pushed the feat/value_stats_filter branch 3 times, most recently from 7aa2715 to 1449d94 Compare July 8, 2026 09:41
@gripleaf gripleaf marked this pull request as ready for review July 8, 2026 09:45
@gripleaf gripleaf changed the title [WIP] feat: add read-optimized system table feat: add read-optimized system table Jul 8, 2026
@gripleaf gripleaf force-pushed the feat/value_stats_filter branch from 1449d94 to b125cf8 Compare July 9, 2026 06:33
@lxy-9602

lxy-9602 commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

@suxiaogang223 Would you mind helping take a look when you have time, since you’re most familiar with system table. Thanks a lot!

Comment thread src/paimon/core/table/source/table_scan.cpp
Comment thread src/paimon/core/table/system/read_optimized_system_table.cpp
Status WriteAndFullCompact(TestHelper* helper, std::unique_ptr<RecordBatch>&& batch,
int64_t commit_identifier) {
PAIMON_RETURN_NOT_OK(helper->write_->Write(std::move(batch)));
PAIMON_RETURN_NOT_OK(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Could you place the output parameter at the end of the parameter list?

.ok());
ASSERT_TRUE(result.array->Equals(expected)) << result.array->ToString();
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Could you add a test case to verify that system table reads support partial-column projection and that predicate pushdown is effective? For the predicate setup, you can refer to NestedColumnPruningInteTest.NestedStructMapSelectedKeysWithPredicate. If the Parquet/ORC row group or stripe boundaries are configured properly, the test should be able to observe and validate that predicate pushdown is actually taking effect.

Comment thread test/inte/read_inte_test.cpp
Comment thread include/paimon/read_context.h
TestHelper::Create(dir->Str(), schema,
/*partition_keys=*/{},
/*primary_keys=*/{}, options,
/*is_streaming_mode=*/true));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

What I’m really trying to test here is predicate behavior on PK tables, because RO tables additionally enable EnableValueFilter, which could affect the result.

/*expected_commit_messages=*/std::nullopt));

ASSERT_OK_AND_ASSIGN(SystemTableReadResult result,
ReadSystemTable(table_path + "$ro", options, /*streaming_mode=*/true));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

please call ReadSystemTable multiple times if you want to test StreamingScan

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@lszskye I think there may be a small misunderstanding here. ReadSystemTable performs a scan first and then reads. What we usually mean by streaming read is doing a single scan and then reading in a while loop from that same scan, rather than calling ReadSystemTable multiple times. For reference, please see TestWithPKWithDvStreamFromSnapshot4 in scan_and_read_inte_test.cpp.

@gripleaf gripleaf force-pushed the feat/value_stats_filter branch 2 times, most recently from 8a8f999 to 558f889 Compare July 13, 2026 08:41

@suxiaogang223 suxiaogang223 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.

I found two additional issues that are not covered by the existing review threads.

.WithCacheConfig(context->GetCacheConfig())
.WithCache(context->GetCache())
.SetReadFieldNames(context->GetReadFieldNames())
.SetReadFieldIds(context->GetReadFieldIds());

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.

Could we preserve the projected Arrow schema from ReadContext::SetReadSchema() here? The wrapper currently copies field names and IDs only. For nested-column pruning those vectors are normally empty, so $ro silently falls back to the full table schema and may return a different shape from the requested projection. This is separate from the existing top-level projection test; could we transfer or re-export the read schema and add a nested projection test for $ro?

For primary-key tables, ``$ro`` only plans data files from the highest LSM
level, which is the level produced by full compaction. This avoids merging data
from multiple LSM levels during query planning and reading. The tradeoff is that
the result may lag behind the latest committed data until a full compaction

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.

Could we document that $ro does not necessarily represent one coherent older snapshot? Different buckets may complete full compaction at different times, so the top-level files selected from the latest snapshot can contain bucket states produced at different snapshots. The current “may lag” wording does not make this consistency caveat clear.

@gripleaf gripleaf force-pushed the feat/value_stats_filter branch from 558f889 to 5098767 Compare July 13, 2026 12:08
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.

4 participants