This is an automated email from the ASF dual-hosted git repository. starocean999 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 67d54a23024 [fix](statistics)Fix replace table doesn't remove table stat meta memory leak bug. (#49345) 67d54a23024 is described below commit 67d54a23024d64ea49a3d4689e21728938b374d6 Author: James <lijib...@selectdb.com> AuthorDate: Sat Mar 22 11:12:12 2025 +0800 [fix](statistics)Fix replace table doesn't remove table stat meta memory leak bug. (#49345) Fix replace table doesn't remove table stat meta bug. When doing replace table with property swap=false, the old table is removed. In this case, we need to remove the table stats meta object for that table to avoid memory leak. --- .../src/main/java/org/apache/doris/alter/Alter.java | 1 + .../apache/doris/statistics/StatisticsCleaner.java | 19 ++++++++++++------- ...replace_table.grovvy => test_replace_table.groovy} | 17 ++++++++++++----- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/alter/Alter.java b/fe/fe-core/src/main/java/org/apache/doris/alter/Alter.java index e3c65da4046..36df2983aa2 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/alter/Alter.java +++ b/fe/fe-core/src/main/java/org/apache/doris/alter/Alter.java @@ -832,6 +832,7 @@ public class Alter { if (origTable.getType() == TableType.MATERIALIZED_VIEW) { Env.getCurrentEnv().getMtmvService().deregisterMTMV((MTMV) origTable); } + Env.getCurrentEnv().getAnalysisManager().removeTableStats(origTable.getId()); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/statistics/StatisticsCleaner.java b/fe/fe-core/src/main/java/org/apache/doris/statistics/StatisticsCleaner.java index 15be395e590..a1c5fc4edc5 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/statistics/StatisticsCleaner.java +++ b/fe/fe-core/src/main/java/org/apache/doris/statistics/StatisticsCleaner.java @@ -116,19 +116,24 @@ public class StatisticsCleaner extends MasterDaemon { // If ctlName, dbName and tblName exist, it means the table stats is created under new version. // First try to find the table by the given names. If table exists, means the tableMeta is valid, // it should be kept in memory. + boolean tableExist = false; try { - StatisticsUtil.findTable(stats.ctlName, stats.dbName, stats.tblName); - continue; + TableIf table = StatisticsUtil.findTable(stats.ctlName, stats.dbName, stats.tblName); + // Tables may have identical names but different id, e.g. replace table. + tableExist = table.getId() == id; } catch (Exception e) { LOG.debug("Table {}.{}.{} not found.", stats.ctlName, stats.dbName, stats.tblName); } - // If we couldn't find table by names, try to find it in internal catalog. This is to support older - // version which the tableStats object doesn't store the names but only table id. + // If we couldn't find table by names, try to find it in internal catalog by id. + // This is to support older version which the tableStats object doesn't store the names + // but only table id. // We may remove external table's tableStats here, but it's not a big problem. // Because the stats in column_statistics table is still available, - // the only disadvantage is auto analyze may be triggered for this table. - // But it only happens once, the new table stats object will have all the catalog, db and table names. - if (tableExistInInternalCatalog(internalCatalog, id)) { + // the only disadvantage is auto analyze may be triggered for this table again. + // But it only happens once, the new table stats object will have all the catalog, + // db and table names. + // Also support REPLACE TABLE + if (tableExist || tableExistInInternalCatalog(internalCatalog, id)) { continue; } LOG.info("Table {}.{}.{} with id {} not exist, remove its table stats record.", diff --git a/regression-test/suites/statistics/test_replace_table.grovvy b/regression-test/suites/statistics/test_replace_table.groovy similarity index 82% rename from regression-test/suites/statistics/test_replace_table.grovvy rename to regression-test/suites/statistics/test_replace_table.groovy index 08c68c5ac20..e64e8f48416 100644 --- a/regression-test/suites/statistics/test_replace_table.grovvy +++ b/regression-test/suites/statistics/test_replace_table.groovy @@ -17,9 +17,9 @@ suite("test_replace_table") { - sql """drop database if exists test_replace_table""" - sql """create database test_replace_table""" - sql """use test_replace_table""" + sql """drop database if exists test_replace_table_statistics""" + sql """create database test_replace_table_statistics""" + sql """use test_replace_table_statistics""" sql """set global force_sample_analyze=false""" sql """set global enable_auto_analyze=false""" @@ -70,12 +70,19 @@ suite("test_replace_table") { result = sql """show column cached stats t2""" assertEquals(2, result.size()) + def id1 = get_table_id("internal", "test_replace_table_statistics", "t1") + def id2 = get_table_id("internal", "test_replace_table_statistics", "t2") + sql """ALTER TABLE t1 REPLACE WITH TABLE t2 PROPERTIES('swap' = 'false');""" result = sql """show column stats t1""" assertEquals(2, result.size()) result = sql """show column cached stats t1""" assertEquals(2, result.size()) - sql """drop database if exists test_replace_table""" -} + result = sql """show table stats ${id1}""" + assertEquals(0, result.size()) + result = sql """show table stats ${id2}""" + assertEquals(1, result.size()) + sql """drop database if exists test_replace_table_statistics""" +} --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org