Skip to content

Commit c9ab71a

Browse files
Jibing-Lidataroaring
authored andcommitted
[improvement](statistics)Support drop cached stats. (#39367)
Support drop cached stats. Usage: `drop cached stats table_name`
1 parent bbf9772 commit c9ab71a

File tree

5 files changed

+215
-0
lines changed

5 files changed

+215
-0
lines changed

fe/fe-core/src/main/cup/sql_parser.cup

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3288,6 +3288,10 @@ drop_stmt ::=
32883288
{:
32893289
RESULT = new DropStatsStmt(tbl, cols, partitionNames);
32903290
:}
3291+
| KW_DROP KW_CACHED KW_STATS table_name:tbl
3292+
{:
3293+
RESULT = new DropCachedStatsStmt(tbl);
3294+
:}
32913295
| KW_DROP KW_EXPIRED KW_STATS
32923296
{:
32933297
RESULT = new DropStatsStmt(true);
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.apache.doris.analysis;
19+
20+
import org.apache.doris.catalog.DatabaseIf;
21+
import org.apache.doris.catalog.Env;
22+
import org.apache.doris.catalog.TableIf;
23+
import org.apache.doris.common.AnalysisException;
24+
import org.apache.doris.common.ErrorCode;
25+
import org.apache.doris.common.ErrorReport;
26+
import org.apache.doris.common.UserException;
27+
import org.apache.doris.datasource.CatalogIf;
28+
import org.apache.doris.mysql.privilege.PrivPredicate;
29+
import org.apache.doris.qe.ConnectContext;
30+
31+
/**
32+
* Manually drop cached statistics for table and its mv.
33+
* <p>
34+
* syntax:
35+
* DROP CACHED STATS TableName;
36+
*/
37+
public class DropCachedStatsStmt extends DdlStmt {
38+
39+
private final TableName tableName;
40+
41+
private long catalogId;
42+
private long dbId;
43+
private long tblId;
44+
45+
public DropCachedStatsStmt(TableName tableName) {
46+
this.tableName = tableName;
47+
}
48+
49+
@Override
50+
public void analyze(Analyzer analyzer) throws UserException {
51+
super.analyze(analyzer);
52+
if (tableName == null) {
53+
throw new UserException("Should specify a valid table name.");
54+
}
55+
tableName.analyze(analyzer);
56+
String catalogName = tableName.getCtl();
57+
String dbName = tableName.getDb();
58+
String tblName = tableName.getTbl();
59+
CatalogIf catalog = analyzer.getEnv().getCatalogMgr()
60+
.getCatalogOrAnalysisException(catalogName);
61+
DatabaseIf db = catalog.getDbOrAnalysisException(dbName);
62+
TableIf table = db.getTableOrAnalysisException(tblName);
63+
tblId = table.getId();
64+
dbId = db.getId();
65+
catalogId = catalog.getId();
66+
// check permission
67+
checkAnalyzePriv(catalogName, db.getFullName(), table.getName());
68+
}
69+
70+
public long getTblId() {
71+
return tblId;
72+
}
73+
74+
public long getDbId() {
75+
return dbId;
76+
}
77+
78+
public long getCatalogIdId() {
79+
return catalogId;
80+
}
81+
82+
@Override
83+
public String toSql() {
84+
StringBuilder sb = new StringBuilder();
85+
sb.append("DROP CACHED STATS ");
86+
87+
if (tableName != null) {
88+
sb.append(tableName.toSql());
89+
}
90+
91+
return sb.toString();
92+
}
93+
94+
@Override
95+
public String toString() {
96+
return toSql();
97+
}
98+
99+
private void checkAnalyzePriv(String catalogName, String dbName, String tblName) throws AnalysisException {
100+
if (!Env.getCurrentEnv().getAccessManager()
101+
.checkTblPriv(ConnectContext.get(), catalogName, dbName, tblName,
102+
PrivPredicate.DROP)) {
103+
ErrorReport.reportAnalysisException(
104+
ErrorCode.ERR_TABLEACCESS_DENIED_ERROR,
105+
"DROP",
106+
ConnectContext.get().getQualifiedUser(),
107+
ConnectContext.get().getRemoteIP(),
108+
dbName + "." + tblName);
109+
}
110+
}
111+
112+
@Override
113+
public StmtType stmtType() {
114+
return StmtType.DROP;
115+
}
116+
117+
@Override
118+
public RedirectStatus getRedirectStatus() {
119+
return RedirectStatus.NO_FORWARD;
120+
}
121+
}

fe/fe-core/src/main/java/org/apache/doris/qe/DdlExecutor.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
import org.apache.doris.analysis.CreateWorkloadSchedPolicyStmt;
8888
import org.apache.doris.analysis.DdlStmt;
8989
import org.apache.doris.analysis.DropAnalyzeJobStmt;
90+
import org.apache.doris.analysis.DropCachedStatsStmt;
9091
import org.apache.doris.analysis.DropCatalogStmt;
9192
import org.apache.doris.analysis.DropDbStmt;
9293
import org.apache.doris.analysis.DropEncryptKeyStmt;
@@ -406,6 +407,8 @@ public static void execute(Env env, DdlStmt ddlStmt) throws Exception {
406407
ProfileManager.getInstance().cleanProfile();
407408
} else if (ddlStmt instanceof DropStatsStmt) {
408409
env.getAnalysisManager().dropStats((DropStatsStmt) ddlStmt);
410+
} else if (ddlStmt instanceof DropCachedStatsStmt) {
411+
env.getAnalysisManager().dropCachedStats((DropCachedStatsStmt) ddlStmt);
409412
} else if (ddlStmt instanceof KillAnalysisJobStmt) {
410413
env.getAnalysisManager().handleKillAnalyzeStmt((KillAnalysisJobStmt) ddlStmt);
411414
} else if (ddlStmt instanceof CleanQueryStatsStmt) {

fe/fe-core/src/main/java/org/apache/doris/statistics/AnalysisManager.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.apache.doris.analysis.AnalyzeStmt;
2323
import org.apache.doris.analysis.AnalyzeTblStmt;
2424
import org.apache.doris.analysis.DropAnalyzeJobStmt;
25+
import org.apache.doris.analysis.DropCachedStatsStmt;
2526
import org.apache.doris.analysis.DropStatsStmt;
2627
import org.apache.doris.analysis.KillAnalysisJobStmt;
2728
import org.apache.doris.analysis.PartitionNames;
@@ -641,6 +642,13 @@ private ThreadPoolExecutor createThreadPoolForSyncAnalyze() {
641642
StatisticsUtil.getAnalyzeTimeout()));
642643
}
643644

645+
public void dropCachedStats(DropCachedStatsStmt stmt) {
646+
long catalogId = stmt.getCatalogIdId();
647+
long dbId = stmt.getDbId();
648+
long tblId = stmt.getTblId();
649+
dropCachedStats(catalogId, dbId, tblId);
650+
}
651+
644652
public void dropStats(DropStatsStmt dropStatsStmt) throws DdlException {
645653
if (dropStatsStmt.dropExpired) {
646654
Env.getCurrentEnv().getStatisticsCleaner().clear();
@@ -719,6 +727,27 @@ public void submitAsyncDropStatsTask(long catalogId, long dbId, long tableId,
719727
}
720728
}
721729

730+
public void dropCachedStats(long catalogId, long dbId, long tableId) {
731+
TableIf table = StatisticsUtil.findTable(catalogId, dbId, tableId);
732+
StatisticsCache statsCache = Env.getCurrentEnv().getStatisticsCache();
733+
Set<String> columns = table.getSchemaAllIndexes(false)
734+
.stream().map(Column::getName).collect(Collectors.toSet());
735+
for (String column : columns) {
736+
List<Long> indexIds = Lists.newArrayList();
737+
if (table instanceof OlapTable) {
738+
indexIds = ((OlapTable) table).getMvColumnIndexIds(column);
739+
} else {
740+
indexIds.add(-1L);
741+
}
742+
for (long indexId : indexIds) {
743+
statsCache.invalidateColumnStatsCache(catalogId, dbId, tableId, indexId, column);
744+
for (String part : table.getPartitionNames()) {
745+
statsCache.invalidatePartitionColumnStatsCache(catalogId, dbId, tableId, indexId, part, column);
746+
}
747+
}
748+
}
749+
}
750+
722751
public void invalidateLocalStats(long catalogId, long dbId, long tableId, Set<String> columns,
723752
TableStatsMeta tableStats, PartitionNames partitionNames) {
724753
if (tableStats == null) {
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
suite("test_drop_cached_stats") {
19+
20+
sql """drop database if exists test_drop_cached_stats"""
21+
sql """create database test_drop_cached_stats"""
22+
sql """use test_drop_cached_stats"""
23+
sql """set global force_sample_analyze=false"""
24+
sql """set global enable_auto_analyze=false"""
25+
26+
sql """CREATE TABLE drop_cache_test (
27+
key1 int NOT NULL,
28+
value1 varchar(25) NOT NULL,
29+
value2 varchar(125) NOT NULL
30+
)ENGINE=OLAP
31+
DUPLICATE KEY(`key1`)
32+
COMMENT "OLAP"
33+
DISTRIBUTED BY HASH(`key1`) BUCKETS 2
34+
PROPERTIES (
35+
"replication_num" = "1"
36+
)
37+
"""
38+
createMV("create materialized view mv1 as select key1 from drop_cache_test;")
39+
40+
sql """insert into drop_cache_test values (1, "1", "1")"""
41+
sql """analyze table drop_cache_test with sync"""
42+
43+
def result = sql """show column stats drop_cache_test"""
44+
assertEquals(4, result.size())
45+
result = sql """show column cached stats drop_cache_test"""
46+
assertEquals(4, result.size())
47+
48+
sql """drop cached stats drop_cache_test"""
49+
result = sql """show column cached stats drop_cache_test"""
50+
assertEquals(0, result.size())
51+
52+
result = sql """show column stats drop_cache_test"""
53+
assertEquals(4, result.size())
54+
55+
56+
sql """drop database if exists test_drop_cached_stats"""
57+
}
58+

0 commit comments

Comments
 (0)