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

morrysnow pushed a commit to branch branch-3.1
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-3.1 by this push:
     new 9f16fba8cfd branch-3.1: [fix](auto bucket)Fix auto bucket calc 
bucketnum err when partition size is invalid #52801 (#53249)
9f16fba8cfd is described below

commit 9f16fba8cfde6ccfbeacaad95620bca71151d777
Author: deardeng <[email protected]>
AuthorDate: Wed Jul 16 11:00:24 2025 +0800

    branch-3.1: [fix](auto bucket)Fix auto bucket calc bucketnum err when 
partition size is invalid #52801 (#53249)
    
    cherry pick from #52801
---
 .../main/java/org/apache/doris/common/Config.java  |   6 +
 .../org/apache/doris/analysis/ShowDataStmt.java    |   2 +-
 .../apache/doris/catalog/MaterializedIndex.java    |   4 +-
 .../org/apache/doris/catalog/MetadataViewer.java   |   2 +-
 .../java/org/apache/doris/catalog/OlapTable.java   |   2 +-
 .../java/org/apache/doris/catalog/Partition.java   |  14 ++-
 .../main/java/org/apache/doris/catalog/Tablet.java |   5 +-
 .../clone/ColocateTableCheckerAndBalancer.java     |   3 +-
 .../doris/clone/DynamicPartitionScheduler.java     | 136 ++++++++++++++++-----
 .../apache/doris/cloud/CacheHotspotManager.java    |   6 +-
 .../doris/common/proc/TabletHealthProcDir.java     |   2 +-
 .../org/apache/doris/catalog/CatalogTestUtil.java  |   2 +-
 .../doris/catalog/DynamicPartitionTableTest.java   |  46 ++++++-
 .../doris/common/util/AutoBucketUtilsTest.java     |   1 +
 14 files changed, 182 insertions(+), 49 deletions(-)

diff --git a/fe/fe-common/src/main/java/org/apache/doris/common/Config.java 
b/fe/fe-common/src/main/java/org/apache/doris/common/Config.java
index ef8cebdb0ad..ab09c68998f 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/common/Config.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/common/Config.java
@@ -2706,6 +2706,12 @@ public class Config extends ConfigBase {
     })
     public static int autobucket_partition_size_per_bucket_gb = -1;
 
+    @ConfField(mutable = true, masterOnly = true, description = {"Auto 
bucket中计算出的新的分区bucket num超过前一个分区的"
+            + "bucket num的百分比,被认为是异常case报警",
+            "The new partition bucket number calculated in the auto bucket 
exceeds the percentage "
+            + "of the previous partition's bucket number, which is considered 
an abnormal case alert."})
+    public static double autobucket_out_of_bounds_percent_threshold = 0.5;
+
     @ConfField(description = {"(已弃用,被 arrow_flight_max_connection 替代) Arrow 
Flight Server中所有用户token的缓存上限,"
             + "超过后LRU淘汰, arrow flight sql是无状态的协议,连接通常不会主动断开,"
             + "bearer token 从 cache 淘汰的同时会 unregister Connection.",
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowDataStmt.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowDataStmt.java
index c7bee06ffda..bc2ac9d5d7c 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowDataStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowDataStmt.java
@@ -298,7 +298,7 @@ public class ShowDataStmt extends ShowStmt implements 
NotFallbackInParser {
             long remoteSegmentSize = 0;
             for (Partition partition : table.getAllPartitions()) {
                 MaterializedIndex mIndex = partition.getIndex(indexId);
-                indexSize += mIndex.getDataSize(false);
+                indexSize += mIndex.getDataSize(false, false);
                 indexReplicaCount += mIndex.getReplicaCount();
                 indexRowCount += mIndex.getRowCount() == -1 ? 0 : 
mIndex.getRowCount();
                 indexRemoteSize += mIndex.getRemoteDataSize();
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/catalog/MaterializedIndex.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/MaterializedIndex.java
index 5e367b538cd..b5a31a32e1e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/MaterializedIndex.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/MaterializedIndex.java
@@ -173,10 +173,10 @@ public class MaterializedIndex extends MetaObject 
implements GsonPostProcessable
         this.rollupFinishedVersion = -1L;
     }
 
-    public long getDataSize(boolean singleReplica) {
+    public long getDataSize(boolean singleReplica, boolean filterSizeZero) {
         long dataSize = 0;
         for (Tablet tablet : getTablets()) {
-            dataSize += tablet.getDataSize(singleReplica);
+            dataSize += tablet.getDataSize(singleReplica, filterSizeZero);
         }
         return dataSize;
     }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/catalog/MetadataViewer.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/MetadataViewer.java
index 66cdfa5b42d..e44b7ec52c8 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/MetadataViewer.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/MetadataViewer.java
@@ -332,7 +332,7 @@ public class MetadataViewer {
                     for (int i = 0; i < tabletIds.size(); i++) {
                         Tablet tablet = mIndex.getTablet(tabletIds.get(i));
                         long rowCount = tablet.getRowCount(true);
-                        long dataSize = tablet.getDataSize(true);
+                        long dataSize = tablet.getDataSize(true, false);
                         rowCountTabletInfos.set(i, rowCountTabletInfos.get(i) 
+ rowCount);
                         dataSizeTabletInfos.set(i, dataSizeTabletInfos.get(i) 
+ dataSize);
                         totalSize += dataSize;
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java
index b94ccbb42d2..5248744dd98 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java
@@ -1594,7 +1594,7 @@ public class OlapTable extends Table implements 
MTMVRelatedTableIf, GsonPostProc
         long dataSize = 0;
         for (Map.Entry<Long, Partition> entry : idToPartition.entrySet()) {
             rowCount += entry.getValue().getBaseIndex().getRowCount();
-            dataSize += entry.getValue().getBaseIndex().getDataSize(false);
+            dataSize += entry.getValue().getBaseIndex().getDataSize(false, 
false);
         }
         if (rowCount > 0) {
             return dataSize / rowCount;
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Partition.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/Partition.java
index 0468d3a7549..e00bf4b28ef 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Partition.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Partition.java
@@ -291,7 +291,7 @@ public class Partition extends MetaObject {
     public long getDataSize(boolean singleReplica) {
         long dataSize = 0;
         for (MaterializedIndex mIndex : 
getMaterializedIndices(IndexExtState.VISIBLE)) {
-            dataSize += mIndex.getDataSize(singleReplica);
+            dataSize += mIndex.getDataSize(singleReplica, false);
         }
         return dataSize;
     }
@@ -458,7 +458,7 @@ public class Partition extends MetaObject {
 
     public long getAvgRowLength() {
         long rowCount = getBaseIndex().getRowCount();
-        long dataSize = getBaseIndex().getDataSize(false);
+        long dataSize = getBaseIndex().getDataSize(false, false);
         if (rowCount > 0) {
             return dataSize / rowCount;
         } else {
@@ -467,6 +467,14 @@ public class Partition extends MetaObject {
     }
 
     public long getDataLength() {
-        return getBaseIndex().getDataSize(false);
+        return getBaseIndex().getDataSize(false, false);
+    }
+
+    public long getDataSizeExcludeEmptyReplica(boolean singleReplica) {
+        long dataSize = 0;
+        for (MaterializedIndex mIndex : 
getMaterializedIndices(IndexExtState.VISIBLE)) {
+            dataSize += mIndex.getDataSize(singleReplica, true);
+        }
+        return dataSize + getRemoteDataSize();
     }
 }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Tablet.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/Tablet.java
index ea76273e6df..f18460a320d 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Tablet.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Tablet.java
@@ -515,8 +515,11 @@ public class Tablet extends MetaObject {
         return id == tablet.id;
     }
 
-    public long getDataSize(boolean singleReplica) {
+    // ATTN: Replica::getDataSize may zero in cloud and non-cloud
+    // due to dataSize not write to image
+    public long getDataSize(boolean singleReplica, boolean filterSizeZero) {
         LongStream s = replicas.stream().filter(r -> r.getState() == 
ReplicaState.NORMAL)
+                .filter(r -> !filterSizeZero || r.getDataSize() > 0)
                 .mapToLong(Replica::getDataSize);
         return singleReplica ? 
Double.valueOf(s.average().orElse(0)).longValue() : s.sum();
     }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/clone/ColocateTableCheckerAndBalancer.java
 
b/fe/fe-core/src/main/java/org/apache/doris/clone/ColocateTableCheckerAndBalancer.java
index 7727bc77e18..7dc0a9125dd 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/clone/ColocateTableCheckerAndBalancer.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/clone/ColocateTableCheckerAndBalancer.java
@@ -655,7 +655,8 @@ public class ColocateTableCheckerAndBalancer extends 
MasterDaemon {
                                         bucketsSeq.size() + " vs. " + 
replicationNum);
                                 Tablet tablet = index.getTablet(tabletId);
                                 totalReplicaDataSizes.set(tabletOrderIdx,
-                                        
totalReplicaDataSizes.get(tabletOrderIdx) + tablet.getDataSize(true));
+                                        
totalReplicaDataSizes.get(tabletOrderIdx)
+                                        + tablet.getDataSize(true, false));
                                 tabletOrderIdx++;
                             }
                         }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/clone/DynamicPartitionScheduler.java
 
b/fe/fe-core/src/main/java/org/apache/doris/clone/DynamicPartitionScheduler.java
index 8e5f46573ee..572db637f9e 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/clone/DynamicPartitionScheduler.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/clone/DynamicPartitionScheduler.java
@@ -58,6 +58,7 @@ import org.apache.doris.persist.PartitionPersistInfo;
 import org.apache.doris.rpc.RpcException;
 import org.apache.doris.thrift.TStorageMedium;
 
+import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
@@ -159,7 +160,7 @@ public class DynamicPartitionScheduler extends MasterDaemon 
{
     }
 
     // exponential moving average
-    private static long ema(ArrayList<Long> history, int period) {
+    private static long ema(List<Long> history, int period) {
         double alpha = 2.0 / (period + 1);
         double ema = history.get(0);
         for (int i = 1; i < history.size(); i++) {
@@ -168,7 +169,7 @@ public class DynamicPartitionScheduler extends MasterDaemon 
{
         return (long) ema;
     }
 
-    private static long getNextPartitionSize(ArrayList<Long> 
historyPartitionsSize) {
+    private static long getNextPartitionSize(List<Long> historyPartitionsSize) 
{
         if (historyPartitionsSize.size() < 2) {
             return historyPartitionsSize.get(0);
         }
@@ -191,65 +192,98 @@ public class DynamicPartitionScheduler extends 
MasterDaemon {
         }
     }
 
-    private static int getBucketsNum(DynamicPartitionProperty property, 
OlapTable table,
+    private static Pair<Integer, Integer> 
getBucketsNum(DynamicPartitionProperty property, OlapTable table,
             String partitionName, String nowPartitionName, boolean 
executeFirstTime) {
         // if execute first time, all partitions no contain data
         if (!table.isAutoBucket() || executeFirstTime) {
-            return property.getBuckets();
+            return Pair.of(property.getBuckets(), 0);
         }
 
-        // auto bucket
-        // get all history partitions
-        RangePartitionInfo info = (RangePartitionInfo) 
(table.getPartitionInfo());
-        List<Map.Entry<Long, PartitionItem>> idToItems = new 
ArrayList<>(info.getIdToItem(false).entrySet());
-        idToItems.sort(Comparator.comparing(o -> ((RangePartitionItem) 
o.getValue()).getItems().upperEndpoint()));
-        List<Partition> partitions = idToItems.stream()
-                .map(entry -> table.getPartition(entry.getKey()))
-                .filter(partition -> partition != null && 
!partition.getName().equals(nowPartitionName))
-                .collect(Collectors.toList());
-        List<Long> visibleVersions = null;
+        List<Partition> partitions = getHistoricalPartitions(table, 
nowPartitionName);
+        List<Long> visibleVersions;
         try {
             visibleVersions = Partition.getVisibleVersions(partitions);
         } catch (RpcException e) {
-            LOG.warn("autobucket use property's buckets get visible version 
fail, table: [{}-{}], "
+            LOG.warn("auto bucket use property's buckets get visible version 
fail, table: [{}-{}], "
                     + "partition: {}, buckets num: {}, exception: ",
                     table.getName(), table.getId(), partitionName, 
property.getBuckets(), e);
-            return property.getBuckets();
+            return Pair.of(property.getBuckets(), 0);
         }
 
-        List<Partition> hasDataPartitions = Lists.newArrayList();
+        List<Partition> hasDataPartitions = filterDataPartitions(partitions, 
visibleVersions);
+        if (hasDataPartitions.isEmpty()) {
+            return handleNoDataPartitions(table, partitionName, 
property.getBuckets());
+        }
+
+        return calculateBuckets(hasDataPartitions);
+    }
+
+    private static List<Partition> getHistoricalPartitions(OlapTable table, 
String nowPartitionName) {
+        RangePartitionInfo info = (RangePartitionInfo) 
(table.getPartitionInfo());
+        List<Map.Entry<Long, PartitionItem>> idToItems = new 
ArrayList<>(info.getIdToItem(false).entrySet());
+        idToItems.sort(Comparator.comparing(o -> ((RangePartitionItem) 
o.getValue()).getItems().upperEndpoint()));
+        return idToItems.stream()
+                .map(entry -> table.getPartition(entry.getKey()))
+                .filter(partition -> partition != null && 
!partition.getName().equals(nowPartitionName))
+                .collect(Collectors.toList());
+    }
+
+    private static List<Partition> filterDataPartitions(List<Partition> 
partitions, List<Long> visibleVersions) {
+        Preconditions.checkState(partitions.size() == visibleVersions.size(),
+                String.format("partitions size %d not eq visibleVersions size 
%d, impossible",
+                    partitions.size(), visibleVersions.size()));
+        List<Partition> hasDataPartitions = new ArrayList<>();
         for (int i = 0; i < partitions.size(); i++) {
             if (visibleVersions.get(i) >= 2) {
                 hasDataPartitions.add(partitions.get(i));
             }
         }
+        return hasDataPartitions;
+    }
 
-        // no exist history partition data
-        if (hasDataPartitions.isEmpty()) {
-            LOG.info("autobucket use property's buckets due to all partitions 
no data, table: [{}-{}], "
-                    + "partition: {}, buckets num: {}",
-                    table.getName(), table.getId(), partitionName, 
property.getBuckets());
-            return property.getBuckets();
+    private static Pair<Integer, Integer> handleNoDataPartitions(OlapTable 
table,
+                                                                 String 
partitionName, int defaultBuckets) {
+        LOG.info("auto bucket use property's buckets due to all partitions no 
data, table: [{}-{}], "
+                + "partition: {}, buckets num: {}", table.getName(), 
table.getId(), partitionName, defaultBuckets);
+        return Pair.of(defaultBuckets, 0);
+    }
+
+    private static Pair<Integer, Integer> calculateBuckets(List<Partition> 
hasDataPartitions) {
+        List<Long> partitionSizeArray = new ArrayList<>();
+        List<Long> sizeUnknownArray = new ArrayList<>();
+
+        for (Partition hasDataPartition : hasDataPartitions) {
+            long partitionSize = 
hasDataPartition.getDataSizeExcludeEmptyReplica(true);
+            if (partitionSize <= 0) {
+                sizeUnknownArray.add(partitionSize);
+            } else {
+                partitionSizeArray.add(partitionSize);
+            }
+        }
+
+        int size = hasDataPartitions.size();
+        Preconditions.checkState(size > 0, "hasDataPartitions size must be 
greater than 0");
+        int previousPartitionBucketsNum = hasDataPartitions.get(size - 
1).getDistributionInfo().getBucketNum();
+
+        if (hasDataPartitions.size() == sizeUnknownArray.size()) {
+            LOG.info("TabletStatMgr not synchronized partitions size yet, so 
use previous partition bucket num");
+            return Pair.of(previousPartitionBucketsNum, 
previousPartitionBucketsNum);
         }
 
-        ArrayList<Long> partitionSizeArray = hasDataPartitions.stream()
-                .map(partition -> partition.getAllDataSize(true))
-                .collect(Collectors.toCollection(ArrayList::new));
         long estimatePartitionSize = getNextPartitionSize(partitionSizeArray);
-        // plus 5 for uncompressed data
         long uncompressedPartitionSize = estimatePartitionSize * 5;
         int bucketsNum = 
AutoBucketUtils.getBucketsNum(uncompressedPartitionSize, 
Config.autobucket_min_buckets);
-        LOG.info("autobucket calc with {} history partitions, table: [{}-{}], 
partition: {}, buckets num: {}, "
-                + " estimate partition size: {}, last partitions(partition 
name, local size, remote size): {}",
-                hasDataPartitions.size(), table.getName(), table.getId(), 
partitionName, bucketsNum,
-                estimatePartitionSize,
+
+        LOG.info("auto bucket calc with {} history partitions, {} history 
partitions size not sync size yet,"
+                + " buckets num: {}, estimate partition size: {}, last 
partitions: {}",
+                hasDataPartitions.size(), sizeUnknownArray.size(), bucketsNum, 
estimatePartitionSize,
                 hasDataPartitions.stream()
                         .skip(Math.max(0, hasDataPartitions.size() - 7))
                         .map(partition -> "(" + partition.getName() + ", " + 
partition.getDataSize(true)
                                 + ", " + partition.getRemoteDataSize() + ")")
                         .collect(Collectors.toList()));
 
-        return bucketsNum;
+        return Pair.of(bucketsNum, previousPartitionBucketsNum);
     }
 
     private ArrayList<AddPartitionClause> getAddPartitionClause(Database db, 
OlapTable olapTable,
@@ -356,8 +390,17 @@ public class DynamicPartitionScheduler extends 
MasterDaemon {
 
             DistributionDesc distributionDesc = null;
             DistributionInfo distributionInfo = 
olapTable.getDefaultDistributionInfo();
-            int bucketsNum = getBucketsNum(dynamicPartitionProperty, 
olapTable, partitionName,
+            Pair<Integer, Integer> ret = 
getBucketsNum(dynamicPartitionProperty, olapTable, partitionName,
                     nowPartitionName, executeFirstTime);
+            int bucketsNum = ret.first;
+            int previousPartitionBucketsNum = ret.second;
+            if (olapTable.isAutoBucket()) {
+                int afterCheckAndFixBucketNum = 
checkAndFixAutoBucketCalcNumIsValid(bucketsNum,
+                        previousPartitionBucketsNum);
+                if (afterCheckAndFixBucketNum > 0) {
+                    bucketsNum = afterCheckAndFixBucketNum;
+                }
+            }
             if (distributionInfo.getType() == 
DistributionInfo.DistributionInfoType.HASH) {
                 HashDistributionInfo hashDistributionInfo = 
(HashDistributionInfo) distributionInfo;
                 List<String> distColumnNames = new ArrayList<>();
@@ -374,6 +417,33 @@ public class DynamicPartitionScheduler extends 
MasterDaemon {
         return addPartitionClauses;
     }
 
+    private int checkAndFixAutoBucketCalcNumIsValid(int 
currentPartitionNumBuckets, int previousPartitionNumBuckets) {
+        // previousPartitionBucketsNum == 0, some abnormal case, ignore it
+        if (currentPartitionNumBuckets != 0) {
+            // currentPartitionNumBuckets can be too big
+            if (currentPartitionNumBuckets
+                    > previousPartitionNumBuckets * (1 + 
Config.autobucket_out_of_bounds_percent_threshold)) {
+                LOG.warn("auto bucket calc num may be err, bigger than 
previous too much, plz check. "
+                        + "calc bucket num {}, previous partition bucket num 
{}, percent {}",
+                        currentPartitionNumBuckets, 
previousPartitionNumBuckets,
+                        Config.autobucket_out_of_bounds_percent_threshold);
+                return currentPartitionNumBuckets;
+            }
+            // currentPartitionNumBuckets not too small.
+            // If it is too small, the program will intervene. use 
previousPartitionNumBuckets
+            if (currentPartitionNumBuckets
+                    < previousPartitionNumBuckets * (1 - 
Config.autobucket_out_of_bounds_percent_threshold)) {
+                LOG.warn("auto bucket calc num may be err, smaller than 
previous too much, plz check. "
+                        + "calc bucket num {}, previous partition bucket num 
{}, percent {}",
+                        currentPartitionNumBuckets, 
previousPartitionNumBuckets,
+                        Config.autobucket_out_of_bounds_percent_threshold);
+                return previousPartitionNumBuckets;
+            }
+        }
+        LOG.info("previousPartitionBucketsNum eq 0, check before log");
+        return -1;
+    }
+
     /**
      * If dynamic_partition.storage_medium is set to SSD,
      * ignore hot_partition_num property and set to (SSD, 9999-12-31 23:59:59)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/cloud/CacheHotspotManager.java 
b/fe/fe-core/src/main/java/org/apache/doris/cloud/CacheHotspotManager.java
index 6b7b0e5282a..6797ce45acb 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/cloud/CacheHotspotManager.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/cloud/CacheHotspotManager.java
@@ -501,13 +501,13 @@ public class CacheHotspotManager extends MasterDaemon {
             List<Long> batch = new ArrayList<>();
             long curBatchSize = 0L;
             for (Tablet tablet : entry.getValue()) {
-                if (curBatchSize + tablet.getDataSize(true) > maxSizePerBatch) 
{
+                if (curBatchSize + tablet.getDataSize(true, false) > 
maxSizePerBatch) {
                     batches.add(batch);
                     batch = new ArrayList<>();
                     curBatchSize = 0L;
                 }
                 batch.add(tablet.getId());
-                curBatchSize += tablet.getDataSize(true);
+                curBatchSize += tablet.getDataSize(true, false);
             }
             if (!batch.isEmpty()) {
                 batches.add(batch);
@@ -545,7 +545,7 @@ public class CacheHotspotManager extends MasterDaemon {
                 continue;
             }
             for (Tablet tablet : index.getTablets()) {
-                warmUpTabletsSize += tablet.getDataSize(true);
+                warmUpTabletsSize += tablet.getDataSize(true, false);
                 tablets.add(tablet);
                 if (warmUpTabletsSize >= dstTotalFileCache) {
                     break;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/common/proc/TabletHealthProcDir.java
 
b/fe/fe-core/src/main/java/org/apache/doris/common/proc/TabletHealthProcDir.java
index 6c36a926d08..b1be9c79ab6 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/common/proc/TabletHealthProcDir.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/common/proc/TabletHealthProcDir.java
@@ -262,7 +262,7 @@ public class TabletHealthProcDir implements 
ProcDirInterface {
                                     inconsistentNum++;
                                     inconsistentTabletIds.add(tablet.getId());
                                 }
-                                if (tablet.getDataSize(true) > 
Config.min_bytes_indicate_replica_too_large) {
+                                if (tablet.getDataSize(true, false) > 
Config.min_bytes_indicate_replica_too_large) {
                                     oversizeNum++;
                                     oversizeTabletIds.add(tablet.getId());
                                 }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/catalog/CatalogTestUtil.java 
b/fe/fe-core/src/test/java/org/apache/doris/catalog/CatalogTestUtil.java
index b16d3d15cf7..8a19912d321 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/catalog/CatalogTestUtil.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/catalog/CatalogTestUtil.java
@@ -385,7 +385,7 @@ public class CatalogTestUtil {
             if (tablet == null) {
                 return -1L;
             }
-            return tablet.getDataSize(true);
+            return tablet.getDataSize(true, false);
         } finally {
             olapTable.readUnlock();
         }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/catalog/DynamicPartitionTableTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/catalog/DynamicPartitionTableTest.java
index 9495c048f4b..ad5b1ce0555 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/catalog/DynamicPartitionTableTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/catalog/DynamicPartitionTableTest.java
@@ -1779,6 +1779,7 @@ public class DynamicPartitionTableTest {
         }
         RebalancerTestUtil.updateReplicaDataSize(1, 1, 1);
 
+        Config.autobucket_out_of_bounds_percent_threshold = 0.99;
         String alterStmt1 =
                 "alter table test.test_autobucket_dynamic_partition set 
('dynamic_partition.end' = '2')";
         ExceptionChecker.expectThrowsNoException(() -> alterTable(alterStmt1));
@@ -1789,7 +1790,7 @@ public class DynamicPartitionTableTest {
         partitions.sort(Comparator.comparing(Partition::getId));
         Assert.assertEquals(53, partitions.size());
         Assert.assertEquals(1, partitions.get(partitions.size() - 
1).getDistributionInfo().getBucketNum());
-
+        Config.autobucket_out_of_bounds_percent_threshold = 0.5;
         table.readLock();
         try {
             // first 40 partitions with size 0,  then 13 partitions with size 
100GB(10GB * 10 buckets)
@@ -1826,5 +1827,48 @@ public class DynamicPartitionTableTest {
         Assert.assertEquals(54, partitions.size());
         // 100GB total, 5GB per bucket, should 20 buckets.
         Assert.assertEquals(20, partitions.get(partitions.size() - 
1).getDistributionInfo().getBucketNum());
+
+        // mock partition size eq 0, use back-to-back logic
+        table.readLock();
+        try {
+            // when fe restart, when stat thread not get replica size from 
be/ms, replica size eq 0
+            for (int i = 0; i < 54; i++) {
+                Partition partition = partitions.get(i);
+                partition.updateVisibleVersion(2L);
+                for (MaterializedIndex idx : partition.getMaterializedIndices(
+                        MaterializedIndex.IndexExtState.VISIBLE)) {
+                    if (i < 52) {
+                        Assert.assertEquals(10, idx.getTablets().size());
+                    } else if (i == 52) {
+                        Assert.assertEquals(1, idx.getTablets().size());
+                    } else if (i == 53) {
+                        Assert.assertEquals(20, idx.getTablets().size());
+                    }
+                    for (Tablet tablet : idx.getTablets()) {
+                        for (Replica replica : tablet.getReplicas()) {
+                            replica.updateVersion(3L);
+                            // mock replica size eq 0
+                            replica.setDataSize(0L);
+                            replica.setRowCount(0L);
+                        }
+                    }
+                }
+                Assert.assertEquals(0, partition.getAllDataSize(true));
+            }
+        } finally {
+            table.readUnlock();
+        }
+
+        String alterStmt3 = "alter table 
test.test_autobucket_dynamic_partition set ('dynamic_partition.end' = '4')";
+        ExceptionChecker.expectThrowsNoException(() -> alterTable(alterStmt3));
+        // 54th previous partition size set 53, check back to back logic work
+        partitions.get(53).getDistributionInfo().setBucketNum(53);
+        
Env.getCurrentEnv().getDynamicPartitionScheduler().executeDynamicPartition(tempDynamicPartitionTableInfo,
 false);
+
+        partitions = Lists.newArrayList(table.getAllPartitions());
+        partitions.sort(Comparator.comparing(Partition::getId));
+        Assert.assertEquals(55, partitions.size());
+        // due to partition size eq 0, use previous partition's(54th) bucket 
num
+        Assert.assertEquals(53, partitions.get(partitions.size() - 
1).getDistributionInfo().getBucketNum());
     }
 }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/common/util/AutoBucketUtilsTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/common/util/AutoBucketUtilsTest.java
index bd3e7f9e2a5..f4f364b91ce 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/common/util/AutoBucketUtilsTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/common/util/AutoBucketUtilsTest.java
@@ -138,6 +138,7 @@ public class AutoBucketUtilsTest {
         Config.tablet_checker_interval_ms = 1000;
         Config.tablet_repair_delay_factor_second = 1;
         connectContext = UtFrameUtils.createDefaultCtx();
+        Config.autobucket_partition_size_per_bucket_gb = 1;
     }
 
     @After


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to