This is an automated email from the ASF dual-hosted git repository.

JingsongLi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git


The following commit(s) were added to refs/heads/master by this push:
     new d2a22e0947 [core] Fix level 1 inflation in universal compaction (#9185)
d2a22e0947 is described below

commit d2a22e0947656162a342acf4c8171aaf92a9ca7e
Author: tsreaper <[email protected]>
AuthorDate: Wed Aug 12 13:32:24 2026 +0800

    [core] Fix level 1 inflation in universal compaction (#9185)
---
 .../mergetree/compact/UniversalCompaction.java     | 27 ++++++++--------------
 .../mergetree/compact/UniversalCompactionTest.java | 15 ++++++++++++
 2 files changed, 24 insertions(+), 18 deletions(-)

diff --git 
a/paimon-core/src/main/java/org/apache/paimon/mergetree/compact/UniversalCompaction.java
 
b/paimon-core/src/main/java/org/apache/paimon/mergetree/compact/UniversalCompaction.java
index 396f3c89a2..ce525ffe49 100644
--- 
a/paimon-core/src/main/java/org/apache/paimon/mergetree/compact/UniversalCompaction.java
+++ 
b/paimon-core/src/main/java/org/apache/paimon/mergetree/compact/UniversalCompaction.java
@@ -116,18 +116,9 @@ public class UniversalCompaction implements 
CompactStrategy {
             candidateCount++;
         }
 
-        if (candidateCount == 0) {
-            return Optional.empty();
-        }
-
-        // Level 1 must be compacted with level 0 to avoid producing level 0. 
Include it in the
-        // initial candidates so that the size-ratio check also considers 
level 2 based on the
-        // combined size of level 0 and level 1.
-        if (candidateCount < runs.size() && runs.get(candidateCount).level() 
== 1) {
-            candidateCount++;
-        }
-
-        return Optional.of(pickForSizeRatio(numLevels - 1, runs, 
candidateCount, true));
+        return candidateCount == 0
+                ? Optional.empty()
+                : Optional.of(pickForSizeRatio(numLevels - 1, runs, 
candidateCount, true));
     }
 
     @VisibleForTesting
@@ -172,22 +163,22 @@ public class UniversalCompaction implements 
CompactStrategy {
     public CompactUnit pickForSizeRatio(
             int maxLevel, List<LevelSortedRun> runs, int candidateCount, 
boolean forcePick) {
         long candidateSize = candidateSize(runs, candidateCount);
+        boolean compactionTriggered = forcePick || candidateCount > 1;
         for (int i = candidateCount; i < runs.size(); i++) {
             LevelSortedRun next = runs.get(i);
             if (candidateSize * (100.0 + sizeRatio + ratioForOffPeak()) / 100.0
                     < next.run().totalSize()) {
-                break;
+                if (!compactionTriggered || next.level() > 1) {
+                    break;
+                }
             }
 
             candidateSize += next.run().totalSize();
             candidateCount++;
+            compactionTriggered = true;
         }
 
-        if (forcePick || candidateCount > 1) {
-            return createUnit(runs, maxLevel, candidateCount);
-        }
-
-        return null;
+        return compactionTriggered ? createUnit(runs, maxLevel, 
candidateCount) : null;
     }
 
     private int ratioForOffPeak() {
diff --git 
a/paimon-core/src/test/java/org/apache/paimon/mergetree/compact/UniversalCompactionTest.java
 
b/paimon-core/src/test/java/org/apache/paimon/mergetree/compact/UniversalCompactionTest.java
index 5ac14f9293..a189a3adaf 100644
--- 
a/paimon-core/src/test/java/org/apache/paimon/mergetree/compact/UniversalCompactionTest.java
+++ 
b/paimon-core/src/test/java/org/apache/paimon/mergetree/compact/UniversalCompactionTest.java
@@ -168,6 +168,21 @@ public class UniversalCompactionTest {
         assertThat(results).isEqualTo(new long[] {1, 2, 3});
     }
 
+    @Test
+    public void testFileNumCompactionConsidersLevel2() {
+        UniversalCompaction compaction = ofTesting(200, 1, 3);
+
+        // File count first picks the two level 0 runs. Together with level 1, 
they are large
+        // enough to pick level 2 as well.
+        Optional<CompactUnit> pick =
+                compaction.pick(
+                        3, Arrays.asList(level(0, 10), level(0, 20), level(1, 
97), level(2, 100)));
+
+        assertThat(pick).isPresent();
+        assertThat(pick.get().files()).hasSize(4);
+        assertThat(pick.get().outputLevel()).isEqualTo(2);
+    }
+
     @Test
     public void testExtremeCaseNoOutputLevel0() {
         UniversalCompaction compaction = ofTesting(200, 1, 5);

Reply via email to