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]