Skip to content

[core] Support bucket-first sorting for manifest files - #9792

Merged
JingsongLi merged 3 commits into
apache:masterfrom
jianguotian:perf/manifest-bucket-first-sort
Sep 14, 2026
Merged

JingsongLi merged 3 commits into
apache:masterfrom
jianguotian:perf/manifest-bucket-first-sort

Conversation

@jianguotian

@jianguotian jianguotian commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

Purpose

This is the first layout follow-up split from #9784 after review feedback. #9791 has already merged the independent manifest bucket-pruning change. This PR makes manifest sorting bucket-first by default for fixed-bucket tables.

Changes

  • Select a dedicated BucketSortKey inside createSortKey for fixed-bucket tables.
  • Sort manifest entries by bucket before the configured partition field.
  • Keep the existing partition-only order for dynamic-bucket and bucket-unaware tables; keep RowIdSortKey for data-evolution tables.
  • Compare manifest runs by bucket only when every input manifest has bucket bounds; otherwise conservatively use the existing partition-only comparison for the whole pass.
  • Use the same sort-key selection in manifest compaction dry-run.
  • Do not introduce a new table option.

Forced manifest rewrites, pruning metadata/filter logic, mixed-count pruning, and other optimizations are intentionally excluded.

Production validation

On an isolated Geely snapshot, bucket-first reduced median statement execution from 13.0315 s to 5.8440 s (55.15%, 2.23x), reduced median planning from 9.55 s to 2.30 s (75.92%), and reduced scanned manifests from 14 to 1. It won all 12 alternating paired runs. Correctness matched at 4,280 rows with the same duplicate-preserving fingerprint.

Full setup, raw metrics, correctness checks, and cleanup evidence are recorded in the PR validation comment.

Verification

  • Targeted manifest sorting, schema validation, and rewrite-cleanup tests: 161 run, 0 failures, 0 errors, 1 skipped.
  • Non-fast paimon-core reactor compile: Checkstyle, Spotless, Maven Enforcer, and compilation passed.

@jianguotian
jianguotian marked this pull request as ready for review September 14, 2026 00:14

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

Left comments:

  1. Concept: Sorting should be based on buckets by default; there is no need to introduce a new option.
  2. Implementation: Similar to rowIdSort, if it is a bucketed table, instantiate a new implementation class within createSortKey.

@jianguotian

jianguotian commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author

Geely isolated performance validation is complete.

Setup

  • Baseline: 62cd0fd9fd (current master, including [core] Support bucket pruning for manifest files #9791), immutable bundle SHA-256 2d341684db64c778c7f67da603c00d0f86eb031401239d572d45235c5180f0ad.
  • Measured candidate: 665baa8720, immutable bundle SHA-256 1d655fe8cba2c8d1683c02a1ab5ade243453522e72e2a547dd945b29cb900048.
  • Current PR head fb445e6ad1 addresses review feedback by removing the explicit option and selecting a dedicated BucketSortKey automatically for fixed-bucket tables. The measured bucket-first entry ordering is unchanged.
  • Both layouts were generated from the same source snapshot (2346, schema 48, 18,219,967,325 records) on separate temporary branches.
  • Both compactions used the same partition field (dt), 2 GiB rewrite budget, 32 MiB target manifest size, 1 B full-compaction threshold, and merge minimum count 1. In the measured candidate build, the only layout difference was enabling bucket-first ordering.
  • Reads for both layouts used the same candidate runtime. One warm-up per arm was excluded, then 12 paired runs alternated order (P,B / B,P).

Results

Metric Partition-first Bucket-first Change
Statement execution median 13.0315 s 5.8440 s 55.15% lower / 2.23x faster
Statement execution p95 14.0510 s 6.4505 s 54.09% lower
Planning median 9.55 s 2.30 s 75.92% lower / 4.15x faster
Scanned manifests 14 1 92.86% lower / 14x fewer

Bucket-first won all 12/12 paired runs. The median paired speedup was 2.2326x (range 2.0602x–2.4032x).

All 24 measured queries had identical scan invariants: snapshot 2347, 12,830 skipped files, 54 resulting files, 25 splits, and 1,000 returned rows at the configured result limit.

Correctness was checked without the result limit: both arms returned 4,280 rows and the same duplicate-preserving aggregate fingerprint (763133377736551553611). Both branch snapshots retained schema 48 and the source total record count.

The temporary branches/tag were deleted after measurement. The customer main table was not altered or compacted. The Spark catalog workaround was removed and the session was stopped.

@jianguotian

Copy link
Copy Markdown
Contributor Author

Thanks @JingsongLi, addressed in fb445e6ad1:

  1. Removed manifest-sort.bucket-first; fixed-bucket tables now use bucket-first ordering by default when manifest sort is enabled.
  2. Added a dedicated BucketSortKey, selected inside createSortKey similarly to RowIdSortKey.
  3. Kept partition-only sorting for dynamic/bucket-unaware tables and the existing RowID path for data-evolution tables.
  4. Kept the conservative partition fallback when legacy input manifests lack bucket bounds.

Focused tests pass (151 run, 0 failures, 1 skipped), and the non-fast paimon-core reactor compile passes Checkstyle, Spotless, Maven Enforcer, and compilation.

@JingsongLi

Copy link
Copy Markdown
Contributor

+1

@JingsongLi
JingsongLi merged commit 6b80445 into apache:master Sep 14, 2026
16 of 17 checks passed
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.

2 participants