Code review comment: The most risky bug in this code is: Zero division error when initializing failureRatio if collectSQLList.size() is zero.  You can modify the code like this: ```java                 double failureRatio = collectSQLList.isEmpty() ? 0 : 1.0 * failedNum / collectSQLList.size(); ```

Code before review:
public void collect(ConnectContext context, AnalyzeStatus analyzeStatus) throws Exception {
int parallelism = Math.max(1, context.getSessionVariable().getStatisticCollectParallelism());
List<List<String>> collectSQLList = buildCollectSQLList(parallelism);
long totalCollectSQL = collectSQLList.size();
if (table.isTemporaryTable()) {
context.setSessionId(((OlapTable) table).getSessionId());
}
context.getSessionVariable().setEnableAnalyzePhasePruneColumns(true);
long finishedSQLNum = 0;
long failedNum = 0;
for (List<String> sqlUnion : collectSQLList) {
if (sqlUnion.size() < parallelism) {
context.getSessionVariable().setPipelineDop(parallelism / sqlUnion.size());
} else {
context.getSessionVariable().setPipelineDop(1);
}
String sql = Joiner.on(" UNION ALL ").join(sqlUnion);
try {
collectStatisticSync(sql, context);
} catch (Exception e) {
failedNum++;
LOG.warn("collect statistics task failed in job: {}, {}", this, sql, e);
double failureRatio = 1.0 * failedNum / collectSQLList.size();
if (collectSQLList.size() < 100) {
throw e;
} else if (failureRatio > Config.statistic_full_statistics_failure_tolerance_ratio) {
String message = String.format("collect statistic job failed due to " +
"too many failed tasks: %d/%d, the last failure is %s",
failedNum, collectSQLList.size(), e);
LOG.warn(message, e);
throw new RuntimeException(message, e);
} else {
continue;
}
}
finishedSQLNum++;
analyzeStatus.setProgress(finishedSQLNum * 100 / totalCollectSQL);
GlobalStateMgr.getCurrentState().getAnalyzeMgr().addAnalyzeStatus(analyzeStatus);
}
flushInsertStatisticsData(context, true);
}

Line under review: GlobalStateMgr.getCurrentState().getAnalyzeMgr().addAnalyzeStatus(analyzeStatus);

Code after addressing the review:
public void collect(ConnectContext context, AnalyzeStatus analyzeStatus) throws Exception {
int parallelism = Math.max(1, context.getSessionVariable().getStatisticCollectParallelism());
List<List<String>> collectSQLList = buildCollectSQLList(parallelism);
long totalCollectSQL = collectSQLList.size();
if (table.isTemporaryTable()) {
context.setSessionId(((OlapTable) table).getSessionId());
}
context.getSessionVariable().setEnableAnalyzePhasePruneColumns(true);
long finishedSQLNum = 0;
long failedNum = 0;
Exception lastFailure = null;
for (List<String> sqlUnion : collectSQLList) {
if (sqlUnion.size() < parallelism) {
context.getSessionVariable().setPipelineDop(parallelism / sqlUnion.size());
} else {
context.getSessionVariable().setPipelineDop(1);
}
String sql = Joiner.on(" UNION ALL ").join(sqlUnion);
try {
collectStatisticSync(sql, context);
} catch (Exception e) {
failedNum++;
LOG.warn("collect statistics task failed in job: {}, {}", this, sql, e);
double failureRatio = 1.0 * failedNum / collectSQLList.size();
if (collectSQLList.size() < 100) {
throw e;
} else if (failureRatio > Config.statistic_full_statistics_failure_tolerance_ratio) {
String message = String.format("collect statistic job failed due to " +
"too many failed tasks: %d/%d, the last failure is %s",
failedNum, collectSQLList.size(), e);
LOG.warn(message, e);
throw new RuntimeException(message, e);
} else {
lastFailure = e;
continue;
}
}
finishedSQLNum++;
analyzeStatus.setProgress(finishedSQLNum * 100 / totalCollectSQL);
GlobalStateMgr.getCurrentState().getAnalyzeMgr().addAnalyzeStatus(analyzeStatus);
}
if (lastFailure != null) {
String message = String.format("collect statistic job partially failed but tolerated %d/%d, " +
"last error is %s", failedNum, collectSQLList.size(), lastFailure);
analyzeStatus.setReason(message);
LOG.warn(message);
}
flushInsertStatisticsData(context, true);
}