Repository navigation
Conversation
gripleaf
force-pushed
the
perf/manifest-cache-partition-pruning-20261013
branch
2 times, most recently
from
October 13, 2026 13:23
f9b2aa6 to
8f30c34
Compare
gripleaf
force-pushed
the
perf/manifest-cache-partition-pruning-20261013
branch
2 times, most recently
from
October 13, 2026 14:18
8151e02 to
c5e8472
Compare
gripleaf
marked this pull request as ready for review
October 14, 2026 02:04
2 tasks done
gripleaf
force-pushed
the
perf/manifest-cache-partition-pruning-20261013
branch
from
October 14, 2026 02:29
d286f52 to
eb0dd0b
Compare
Apply early partition selection across manifest reads and snapshot cache hits. Preserve complete cache values, predicate error propagation, and cache recovery. Remove the unused predecessor snapshot lookup interface. Closes apache#433
gripleaf
force-pushed
the
perf/manifest-cache-partition-pruning-20261013
branch
from
October 15, 2026 02:08
eb0dd0b to
0b189c4
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
Linked issue: Closes #433.
Apply partition selection before full manifest-entry decoding across ordinary manifest scans, manifest Arrow-cache reads, and exact snapshot-cache hits. Scans selecting a small subset of partitions can avoid constructing irrelevant
ManifestEntry/DataFileMetaobjects and decoding their statistics, whether or not caching is enabled.Scenario. A partitioned, bucketed Paimon table serves repeated point reads. An application batches 50 requested cells, grouping cells for the same key. Each underlying lookup uses a key equality predicate and a fixed date-partition filter, allowing the planner to select one bucket. The bucket-scoped manifest cache, however, contains live files from many date partitions. Reusing that cache currently decodes the full file metadata before discarding entries outside the requested partition.
For example, one sampled bucket contains 604 live entries across 84 partitions, but only six entries belong to the queried partition:
ManifestFile::ReadSelectedEntriesextends the existing row-range reader to combine row-range and partition selection before deserialization in one scan loop. It uses the existingReadArrowBatchesflow for both disk and Arrow-cache reads. When neither row-range nor partition selection is needed, it delegates to the existingObjectsFile::Readpath. Callers supply every argument explicitly, usingnullptrfor a selection they do not need. The genericObjectsFile::Readinterface and its other consumers are unchanged.FileStoreScansupplies the same partition filter to this reader and to snapshot selection. Both readers validate the entry version before early field access or invoking the row filter.ManifestEntrySerializer::GetPartitionViewborrows partition bytes for synchronous filtering; fully decoded entries retain owned partition data. Entries already selected by partition run only the remaining post-decode filters. ADD and DELETE entries receive the same selection before merging. Existing bucket reader pushdown is preserved.On an exact snapshot-cache hit,
ReadSnapshotselects that retained snapshot and skips other snapshots by serialized row length without allocating their row payloads. It returns a request-local selection; fullDeserializeremains available for cache rebuilding and updates. The shared Arrow cache retains complete batches, and snapshot cache misses rebuild and store the complete bucket before query filtering, so later scans can safely query another partition. Existing snapshot retention and normal miss/rebuild behavior are preserved. Each scan looks up the snapshot cache once. Snapshot selection distinguishes predicate failures from cache parsing failures. Predicate failures propagate toCreatePlanwithout an internal retry. Malformed cache values are treated as misses and rebuilt from the manifests through the existing miss path. A successful read with no retained snapshot uses full deserialization only to retain historical snapshots before rebuilding the target snapshot; a present selection is a cache hit. Error provenance is recorded only atpartition_filter_->Test(), so a failure to decode partition bytes remains a cache parsing failure, even though both sources can returnStatus::Invalid. Unfiltered snapshot reads reserve the known entry count; filtered reads grow with the selected results.The existing
scan.manifest-entry.lazy-decode.enabledoption controls partition selection before metadata decoding on all three paths. Disabling it preserves full entry decoding before partition filtering. The implementation still traverses serialized snapshot payloads and loads aligned batches on disk/Arrow-cache paths; it reduces entry-object and statistics materialization. Scans selecting most partitions are not expected to gain the same benefit.Component measurements (not end-to-end query latency). A standalone prototype harness compared full deserialization followed by partition filtering against selective decoding, using the same serialized cache payloads from four real buckets. Each bucket had 84 partitions; each comparison selected one partition. Each path ran 200 iterations per pair, with five pairs and alternating execution order, on the same host. The table reports mean elapsed time per iteration across those pairs. Both paths returned exactly equal selected entries.
These measurements motivated the upstream port; they are prototype measurements, not measurements of this refactored PR or its disk/Arrow-cache paths. Full cold/warm end-to-end performance and long-running concurrent behavior have not yet been benchmarked for this upstream build.
Tests
All 25 tests in the focused scan suites passed, followed by the complete core suite (2356 passed). The complete common suite also passed (1725 passed, 2 skipped); the skips are the existing prefetch warmup cases without a read-ahead cache to rearm.
All applicable pre-commit checks passed for the PR's 19 changed files. Release, sanitizer, integration suites, and end-to-end performance benchmarks were not run.
Regression coverage:
RowRangeManifestFileTest.PartitionFilterComposesWithRowRangesexercises disk and Arrow-cache reads, partition/range intersection, ADD/DELETE merging, filter errors, and skipped metadata decoding.SchemaEvolutionAndVersionValidationalso checks that an unsupported version is rejected before the row filter is invoked.AppendOnlyFileStoreScanTest.PartitionPruningAcrossCacheModescovers uncached, Arrow-cache, and snapshot-cache reads with lazy decoding enabled and disabled. It checks partition results, one partition predicate evaluation per candidate, cache reuse, single snapshot-cache lookups, empty results, and later unfiltered reads.PartitionPruningSkipsExcludedMetadataInCreatePlanproves the scan wires early partition selection into each read path: an invalid file kind in an excluded partition is skipped with lazy decoding enabled and rejected when it is disabled.SnapshotCachePropagatesPartitionPredicateErrorinjects one-timeIOErrorandInvalidpredicate failures and checks thatCreatePlanpropagates their codes and messages without internally retrying, with lazy decoding enabled and disabled. A subsequent caller retry succeeds using the complete cached snapshot.SnapshotCacheRebuildsCorruptValuesinjects bad magic, unsupported entry versions, truncated rows, and invalid partition bytes into the snapshot cache. With lazy decoding enabled and disabled, the first scan rebuilds and matches an uncached scan, the second scan hits the repaired cache, and an unfiltered scan still returns the complete bucket.TestSnapshotLiveManifestCacheRebuildOnMisschecks historical snapshot retention and reduced retention limits configured throughScanContextBuilder.LatestBeforeOrEqual/Entryinterface has been removed. Snapshot tests retain serialization round-trip and eviction coverage through the supported APIs. Snapshot selection tests cover exact hits/misses, retention, empty snapshots, allocation-free skipping of other snapshots, malformed headers, filter errors, and version validation before filtering.API and Format
No public API symbols, metric names, serialized cache format, table storage format, or protocols are added or changed. The existing lazy-decode option documentation describes its broader scope.
ReadSelectedEntriesand exact snapshot selection are internal APIs. Snapshot selection returns its pre-filter candidate count to preserve the meaning of existing lazy-scan metrics.The private shared
SerializationUtilsdecoder now also rejects binary rows whose declared arity requires more fixed-field bytes than the payload contains, using overflow-safe bounds checks. This tightens validation for both borrowed and owned inputs, including existing consumers such as file keys, statistics, splits, and commit messages. Well-formed serialized rows and their encoding are unchanged. The check remains shared rather than being limited to partition views.Predicate evaluation failures during selective snapshot reading propagate to the caller. Errors parsing cached values, including malformed headers, unsupported entry versions, truncated payloads, and invalid partition bytes, retain the existing recovery behavior: rebuild the complete bucket from manifests and write it back to the cache. Normal snapshot misses retain historical snapshots through full deserialization. Cache lookup failure handling is unchanged.
Documentation
Updated
manifest_entry_cache.rstwith selective decoding across read sources, row-range composition, option behavior, the original motivating example, and cache completeness guarantees. Updated the existing option comment ininclude/paimon/defs.h.Generative AI tooling
Generated-by: OpenAI Codex (codex-cli 0.162.1)