[core] Cache projected schemas for data evolution stats - #9046
Conversation
4eb6848 to
10835fe
Compare
|
Thanks for the follow-ups — the cached field-lookup map removes the O(F²) matching loop, and the projection-isolation test is a nice addition. With those in I re-ran the numbers (1027 cols × 2000 row-id groups, single layout):
Two remaining suggestions:
|
| @VisibleForTesting | ||
| static class EvolutionStatsCache { | ||
|
|
||
| private final Map<Triple<Long, List<String>, List<String>>, ProjectedFileSchema> cache = |
There was a problem hiding this comment.
Introduce a class for the key, so we can know what is what.
| } | ||
|
|
||
| @VisibleForTesting | ||
| static class EvolutionStatsCache { |
There was a problem hiding this comment.
Can be a separate class.
| List<DataField> fields = dataFileSchema.fields(); | ||
| Map<Integer, Integer> fieldIdToStatsIndex = new HashMap<>(fields.size() * 2); | ||
| for (DataField field : fields) { | ||
| fieldIdToStatsIndex.put(field.id(), NO_STATS_FIELD_INDEX); |
There was a problem hiding this comment.
Could we avoid encoding three domain states (null = field absent, -1 = field present without stats, and >= 0 = stats position) in a Map<Integer, Integer>? A typed value such as FileFieldStats.withoutStats() / withStats(index, type) would preserve the single O(1) lookup, keep the stats index and type together, and confine integer sentinels to the DataEvolutionRow / DataEvolutionArray boundary.
6a9d333 to
71f4b2c
Compare
|
+1 |
Purpose
DataEvolutionFileStoreScan.evolutionStatsruns once per Row-ID group and repeatedly resolves the same projected file schemas and field positions. This becomes expensive for wide data-evolution tables with many groups, even when the snapshot contains only a few distinct physical column layouts.This change adds a scan-local cache keyed by
(schemaId, writeCols, valueStatsCols). Each cache entry reuses:-1represents a physically present field without stats;The lookup map is built only on a projection-cache miss, rather than once per file or Row-ID group.
evolutionStatsalso precomputes target field types and stops scanning older files after all fields have been resolved.evolutionStatsaccepts the cache explicitly. Normal scan planning passes one cache across all Row-ID groups, while standalone tests can pass a fresh cache.Benchmark
Replayed a real-world metadata snapshot with:
Hot-run averages:
master: 45.71 seconds;The final implementation is 9.83x faster than
masterand 2.30x faster than the initial projected-schema-cache implementation. All variants produced zero candidate files.Tests
mvn -pl paimon-core -am -Pfast-build -DfailIfNoTests=false -DwildcardSuites=none -Dtest=DataEvolutionFileStoreScanTest testmvn -pl paimon-core -am -Pfast-build -DfailIfNoTests=false -DwildcardSuites=none -Dtest='*DataEvolution*Test' test(208 tests)