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

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


The following commit(s) were added to refs/heads/master by this push:
     new 12d1694c9cf [fix](statistics) Enhance OOM error message for statistics 
analyze tasks (#63172)
12d1694c9cf is described below

commit 12d1694c9cf044ee153805b9a0af09bd5f3995e8
Author: Wen Zhenghu <[email protected]>
AuthorDate: Thu May 14 14:16:38 2026 +0800

    [fix](statistics) Enhance OOM error message for statistics analyze tasks 
(#63172)
    
    ### What problem does this PR solve?
    
    Problem Summary:
    1. Enhance OOM error message during internal analyze tasks. The original
    error incorrectly suggested modifying `exec_mem_limit`. The new message
    now correctly advises users to increase
    `statistics_sql_mem_limit_in_bytes` or decrease
    `huge_table_default_sample_rows` to reduce memory usage, or use
    `statistics_max_string_column_length` to skip large string columns.
    2. Added FE unit tests for `AnalysisTaskWrapper` to verify the error
    message replacement logic.
    
    ### Release note
    
    Enhance the OOM error message during internal analyze tasks to provide
    actionable tuning suggestions.
---
 .../main/java/org/apache/doris/common/Config.java  |  2 +-
 .../doris/statistics/AnalysisTaskWrapper.java      | 16 ++++-
 .../doris/statistics/AnalysisTaskWrapperTest.java  | 84 ++++++++++++++++++++++
 3 files changed, 99 insertions(+), 3 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 63cec327c20..2dec4a2222a 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
@@ -2533,7 +2533,7 @@ public class Config extends ConfigBase {
     @ConfField
     public static int statistics_sql_parallel_exec_instance_num = 1;
 
-    @ConfField
+    @ConfField(mutable = true)
     public static long statistics_sql_mem_limit_in_bytes = 2L * 1024 * 1024 * 
1024;
 
     @ConfField(mutable = true, masterOnly = true, description = {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/statistics/AnalysisTaskWrapper.java 
b/fe/fe-core/src/main/java/org/apache/doris/statistics/AnalysisTaskWrapper.java
index b856420ba05..9806285c7e2 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/statistics/AnalysisTaskWrapper.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/statistics/AnalysisTaskWrapper.java
@@ -32,6 +32,9 @@ import java.util.concurrent.FutureTask;
 public class AnalysisTaskWrapper extends FutureTask<Void> {
 
     private static final Logger LOG = 
LogManager.getLogger(AnalysisTaskWrapper.class);
+    private static final String STATISTICS_ANALYZE_OOM_HINT = "For statistics 
analyze, you can increase "
+            + "`statistics_sql_mem_limit_in_bytes`, decrease 
`huge_table_default_sample_rows`, "
+            + "or use `statistics_max_string_column_length` to skip large 
string columns.";
 
     private final BaseAnalysisTask task;
 
@@ -78,7 +81,7 @@ public class AnalysisTaskWrapper extends FutureTask<Void> {
                     if (MetricRepo.isInit) {
                         
MetricRepo.COUNTER_STATISTICS_FAILED_ANALYZE_TASK.increase(1L);
                     }
-                    task.job.taskFailed(task, 
Util.getRootCauseMessage(except));
+                    task.job.taskFailed(task, 
appendStatisticsAnalyzeOOMHint(Util.getRootCauseMessage(except)));
                 } else {
                     if (MetricRepo.isInit) {
                         
MetricRepo.COUNTER_STATISTICS_SUCCEED_ANALYZE_TASK.increase(1L);
@@ -93,12 +96,21 @@ public class AnalysisTaskWrapper extends FutureTask<Void> {
             LOG.warn("{} cancelled, cost time:{}", task.toString(), 
System.currentTimeMillis() - startTime);
             task.cancel();
         } catch (Exception e) {
-            LOG.warn(String.format("Cancel job failed job info : %s", msg));
+            LOG.warn(String.format("Cancel job failed job info : %s",
+                    
appendStatisticsAnalyzeOOMHint(Util.getRootCauseMessage(e))));
         }
         // Interrupt thread when it's writing metadata would cause FE crush.
         return super.cancel(false);
     }
 
+    private String appendStatisticsAnalyzeOOMHint(String msg) {
+        if (msg == null || !msg.contains("MEM_LIMIT_EXCEEDED")
+                || msg.contains("statistics_sql_mem_limit_in_bytes")) {
+            return msg;
+        }
+        return msg + "\n" + STATISTICS_ANALYZE_OOM_HINT;
+    }
+
     public long getStartTime() {
         return startTime;
     }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/statistics/AnalysisTaskWrapperTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/statistics/AnalysisTaskWrapperTest.java
new file mode 100644
index 00000000000..e0d3b545164
--- /dev/null
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/statistics/AnalysisTaskWrapperTest.java
@@ -0,0 +1,84 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.statistics;
+
+import org.apache.doris.catalog.Env;
+import org.apache.doris.common.DdlException;
+import org.apache.doris.statistics.AnalysisInfo.ScheduleType;
+
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+public class AnalysisTaskWrapperTest {
+
+    @Test
+    public void testOOMErrorMessageReplacement() throws Exception {
+        AnalysisInfo analysisInfo = new 
AnalysisInfoBuilder().setJobId(1).setTaskId(2)
+                .setScheduleType(ScheduleType.ONCE).build();
+        AnalysisJob mockJob = Mockito.mock(AnalysisJob.class);
+
+        BaseAnalysisTask task = new BaseAnalysisTask() {
+            @Override
+            public void execute() throws Exception {
+                doExecute();
+            }
+
+            @Override
+            public void doExecute() throws Exception {
+                throw new Exception("(172.16.0.90)[MEM_LIMIT_EXCEEDED]PreCatch 
error code:11, "
+                        + "[E11] Allocator mem tracker check failed... can 
`set exec_mem_limit` to change limit, "
+                        + "details see be.INFO.");
+            }
+
+            @Override
+            protected void doSample() {
+            }
+
+            @Override
+            protected void deleteNotExistPartitionStats(AnalysisInfo jobInfo) 
throws DdlException {
+            }
+
+            @Override
+            public String toString() {
+                return "test-analysis-task";
+            }
+        };
+        task.info = analysisInfo;
+        task.job = mockJob;
+
+        try (MockedStatic<Env> mockedEnv = Mockito.mockStatic(Env.class, 
Mockito.CALLS_REAL_METHODS)) {
+            mockedEnv.when(Env::isCheckpointThread).thenReturn(true);
+            AnalysisTaskExecutor executor = new AnalysisTaskExecutor(1);
+            AnalysisTaskWrapper wrapper = new AnalysisTaskWrapper(executor, 
task);
+
+            wrapper.run();
+        }
+
+        ArgumentCaptor<String> msgCaptor = 
ArgumentCaptor.forClass(String.class);
+        Mockito.verify(mockJob).taskFailed(Mockito.eq(task), 
msgCaptor.capture());
+        String errorMsg = msgCaptor.getValue();
+        Mockito.verifyNoMoreInteractions(mockJob);
+        org.junit.jupiter.api.Assertions.assertTrue(errorMsg.contains("can 
`set exec_mem_limit` to change limit"));
+        org.junit.jupiter.api.Assertions.assertTrue(
+                errorMsg.contains("For statistics analyze, you can increase 
`statistics_sql_mem_limit_in_bytes`, "
+                        + "decrease `huge_table_default_sample_rows`, "
+                        + "or use `statistics_max_string_column_length` to 
skip large string columns."));
+    }
+}


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

Reply via email to