Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature](statistics)Support enable/disable auto analyze for table. #39532

Merged
merged 1 commit into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 44 additions & 8 deletions fe/fe-core/src/main/java/org/apache/doris/alter/Alter.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import org.apache.doris.catalog.Column;
import org.apache.doris.catalog.DataProperty;
import org.apache.doris.catalog.Database;
import org.apache.doris.catalog.DatabaseIf;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.MTMV;
import org.apache.doris.catalog.MysqlTable;
Expand All @@ -53,6 +54,7 @@
import org.apache.doris.catalog.PartitionInfo;
import org.apache.doris.catalog.ReplicaAllocation;
import org.apache.doris.catalog.Table;
import org.apache.doris.catalog.TableIf;
import org.apache.doris.catalog.TableIf.TableType;
import org.apache.doris.catalog.View;
import org.apache.doris.cloud.alter.CloudSchemaChangeHandler;
Expand All @@ -65,13 +67,15 @@
import org.apache.doris.common.util.MetaLockUtils;
import org.apache.doris.common.util.PropertyAnalyzer;
import org.apache.doris.common.util.PropertyAnalyzer.RewriteProperty;
import org.apache.doris.datasource.ExternalTable;
import org.apache.doris.nereids.trees.plans.commands.info.TableNameInfo;
import org.apache.doris.persist.AlterMTMV;
import org.apache.doris.persist.AlterViewInfo;
import org.apache.doris.persist.BatchModifyPartitionsInfo;
import org.apache.doris.persist.ModifyCommentOperationLog;
import org.apache.doris.persist.ModifyPartitionInfo;
import org.apache.doris.persist.ModifyTableEngineOperationLog;
import org.apache.doris.persist.ModifyTablePropertyOperationLog;
import org.apache.doris.persist.ReplaceTableOperationLog;
import org.apache.doris.policy.StoragePolicy;
import org.apache.doris.qe.ConnectContext;
Expand Down Expand Up @@ -303,6 +307,24 @@ private boolean processAlterOlapTable(AlterTableStmt stmt, OlapTable olapTable,
return needProcessOutsideTableLock;
}

private void setExternalTableAutoAnalyzePolicy(ExternalTable table, List<AlterClause> alterClauses) {
Preconditions.checkState(alterClauses.size() == 1);
AlterClause alterClause = alterClauses.get(0);
Preconditions.checkState(alterClause instanceof ModifyTablePropertiesClause);
Map<String, String> properties = alterClause.getProperties();
Preconditions.checkState(properties.size() == 1);
Preconditions.checkState(properties.containsKey(PropertyAnalyzer.PROPERTIES_AUTO_ANALYZE_POLICY));
String value = properties.get(PropertyAnalyzer.PROPERTIES_AUTO_ANALYZE_POLICY);
Preconditions.checkState(PropertyAnalyzer.ENABLE_AUTO_ANALYZE_POLICY.equalsIgnoreCase(value)
|| PropertyAnalyzer.DISABLE_AUTO_ANALYZE_POLICY.equalsIgnoreCase(value)
|| PropertyAnalyzer.USE_CATALOG_AUTO_ANALYZE_POLICY.equalsIgnoreCase(value));
value = value.equalsIgnoreCase(PropertyAnalyzer.USE_CATALOG_AUTO_ANALYZE_POLICY) ? null : value;
table.getCatalog().setAutoAnalyzePolicy(table.getDatabase().getFullName(), table.getName(), value);
ModifyTablePropertyOperationLog info = new ModifyTablePropertyOperationLog(table.getCatalog().getName(),
table.getDatabase().getFullName(), table.getName(), properties);
Env.getCurrentEnv().getEditLog().logModifyTableProperties(info);
}

private boolean needChangeMTMVState(List<AlterClause> alterClauses) {
for (AlterClause alterClause : alterClauses) {
if (alterClause.needChangeMTMVState()) {
Expand Down Expand Up @@ -467,31 +489,45 @@ private void processModifyEngineInternal(Database db, Table externalTable,

public void processAlterTable(AlterTableStmt stmt) throws UserException {
TableName dbTableName = stmt.getTbl();
String ctlName = dbTableName.getCtl();
String dbName = dbTableName.getDb();
String tableName = dbTableName.getTbl();
Database db = Env.getCurrentInternalCatalog().getDbOrDdlException(dbName);
Table table = db.getTableOrDdlException(tableName);
DatabaseIf dbIf = Env.getCurrentEnv().getCatalogMgr()
.getCatalogOrException(ctlName, catalog -> new DdlException("Unknown catalog " + catalog))
.getDbOrDdlException(dbName);
TableIf tableIf = dbIf.getTableOrDdlException(tableName);
List<AlterClause> alterClauses = Lists.newArrayList();
// some operations will take long time to process, need to be done outside the table lock
boolean needProcessOutsideTableLock = false;
switch (table.getType()) {
switch (tableIf.getType()) {
case MATERIALIZED_VIEW:
case OLAP:
OlapTable olapTable = (OlapTable) table;
needProcessOutsideTableLock = processAlterOlapTable(stmt, olapTable, alterClauses, db);
OlapTable olapTable = (OlapTable) tableIf;
needProcessOutsideTableLock = processAlterOlapTable(stmt, olapTable, alterClauses, (Database) dbIf);
break;
case ODBC:
case JDBC:
case HIVE:
case MYSQL:
case ELASTICSEARCH:
processAlterExternalTable(stmt, table, db);
processAlterExternalTable(stmt, (Table) tableIf, (Database) dbIf);
return;
case HMS_EXTERNAL_TABLE:
case JDBC_EXTERNAL_TABLE:
case ICEBERG_EXTERNAL_TABLE:
case PAIMON_EXTERNAL_TABLE:
case MAX_COMPUTE_EXTERNAL_TABLE:
case HUDI_EXTERNAL_TABLE:
case TRINO_CONNECTOR_EXTERNAL_TABLE:
alterClauses.addAll(stmt.getOps());
Jibing-Li marked this conversation as resolved.
Show resolved Hide resolved
setExternalTableAutoAnalyzePolicy((ExternalTable) tableIf, alterClauses);
return;
default:
throw new DdlException("Do not support alter "
+ table.getType().toString() + " table[" + tableName + "]");
+ tableIf.getType().toString() + " table[" + tableName + "]");
}

Database db = (Database) dbIf;
// the following ops should done outside table lock. because it contain synchronized create operation
if (needProcessOutsideTableLock) {
Preconditions.checkState(alterClauses.size() == 1);
Expand All @@ -514,7 +550,7 @@ public void processAlterTable(AlterTableStmt stmt) throws UserException {
List<String> partitionNames = clause.getPartitionNames();
((SchemaChangeHandler) schemaChangeHandler).updatePartitionsProperties(
db, tableName, partitionNames, properties);
OlapTable olapTable = (OlapTable) table;
OlapTable olapTable = (OlapTable) tableIf;
olapTable.writeLockOrDdlException();
try {
modifyPartitionsProperty(db, olapTable, partitionNames, properties, clause.isTempPartition());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2288,7 +2288,8 @@ public void updateTableProperties(Database db, String tableName, Map<String, Str
|| properties.containsKey(PropertyAnalyzer.PROPERTIES_DISABLE_AUTO_COMPACTION)
|| properties.containsKey(PropertyAnalyzer.PROPERTIES_SKIP_WRITE_INDEX_ON_LOAD)
|| properties.containsKey(PropertyAnalyzer.PROPERTIES_TIME_SERIES_COMPACTION_EMPTY_ROWSETS_THRESHOLD)
|| properties.containsKey(PropertyAnalyzer.PROPERTIES_TIME_SERIES_COMPACTION_LEVEL_THRESHOLD));
|| properties.containsKey(PropertyAnalyzer.PROPERTIES_TIME_SERIES_COMPACTION_LEVEL_THRESHOLD)
|| properties.containsKey(PropertyAnalyzer.PROPERTIES_AUTO_ANALYZE_POLICY));

Env.getCurrentEnv().getAlterInstance().checkNoForceProperty(properties);
List<Partition> partitions = Lists.newArrayList();
Expand Down Expand Up @@ -2364,7 +2365,8 @@ public void updateTableProperties(Database db, String tableName, Map<String, Str
&& !properties.containsKey(PropertyAnalyzer.PROPERTIES_DISABLE_AUTO_COMPACTION)
&& !properties.containsKey(PropertyAnalyzer.PROPERTIES_GROUP_COMMIT_INTERVAL_MS)
&& !properties.containsKey(PropertyAnalyzer.PROPERTIES_GROUP_COMMIT_DATA_BYTES)
&& !properties.containsKey(PropertyAnalyzer.PROPERTIES_SKIP_WRITE_INDEX_ON_LOAD)) {
&& !properties.containsKey(PropertyAnalyzer.PROPERTIES_SKIP_WRITE_INDEX_ON_LOAD)
&& !properties.containsKey(PropertyAnalyzer.PROPERTIES_AUTO_ANALYZE_POLICY)) {
LOG.info("Properties already up-to-date");
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import org.apache.doris.common.UserException;
import org.apache.doris.common.util.InternalDatabaseUtil;
import org.apache.doris.common.util.PropertyAnalyzer;
import org.apache.doris.common.util.Util;
import org.apache.doris.mysql.privilege.PrivPredicate;
import org.apache.doris.qe.ConnectContext;

Expand Down Expand Up @@ -66,8 +65,6 @@ public void analyze(Analyzer analyzer) throws UserException {
ErrorReport.reportAnalysisException(ErrorCode.ERR_NO_TABLES_USED);
}
tbl.analyze(analyzer);
// disallow external catalog
Util.prohibitExternalCatalog(tbl.getCtl(), this.getClass().getSimpleName());
InternalDatabaseUtil.checkDatabase(tbl.getDb(), ConnectContext.get());
if (!Env.getCurrentEnv().getAccessManager()
.checkTblPriv(ConnectContext.get(), tbl.getCtl(), tbl.getDb(), tbl.getTbl(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.apache.doris.common.util.DynamicPartitionUtil;
import org.apache.doris.common.util.PrintableMap;
import org.apache.doris.common.util.PropertyAnalyzer;
import org.apache.doris.datasource.InternalCatalog;

import com.google.common.base.Strings;

Expand Down Expand Up @@ -350,6 +351,19 @@ public void analyze(Analyzer analyzer) throws AnalysisException {
// do nothing, will be analyzed when creating alter job
} else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_ROW_STORE_COLUMNS)) {
// do nothing, will be analyzed when creating alter job
} else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_AUTO_ANALYZE_POLICY)) {
String analyzePolicy = properties.getOrDefault(PropertyAnalyzer.PROPERTIES_AUTO_ANALYZE_POLICY, "");
if (analyzePolicy != null
&& !analyzePolicy.equals(PropertyAnalyzer.ENABLE_AUTO_ANALYZE_POLICY)
&& !analyzePolicy.equals(PropertyAnalyzer.DISABLE_AUTO_ANALYZE_POLICY)
&& !analyzePolicy.equals(PropertyAnalyzer.USE_CATALOG_AUTO_ANALYZE_POLICY)) {
throw new AnalysisException(
"Table auto analyze policy only support for " + PropertyAnalyzer.ENABLE_AUTO_ANALYZE_POLICY
+ " or " + PropertyAnalyzer.DISABLE_AUTO_ANALYZE_POLICY
+ " or " + PropertyAnalyzer.USE_CATALOG_AUTO_ANALYZE_POLICY);
}
this.needTableStable = false;
this.opType = AlterOpType.MODIFY_TABLE_PROPERTY_SYNC;
} else {
throw new AnalysisException("Unknown table property: " + properties.keySet());
}
Expand All @@ -358,6 +372,10 @@ public void analyze(Analyzer analyzer) throws AnalysisException {

private void analyzeForMTMV() throws AnalysisException {
if (tableName != null) {
// Skip external catalog.
if (!(InternalCatalog.INTERNAL_CATALOG_NAME.equals(tableName.getCtl()))) {
return;
}
Table table = Env.getCurrentInternalCatalog().getDbOrAnalysisException(tableName.getDb())
.getTableOrAnalysisException(tableName.getTbl());
if (!(table instanceof MTMV)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public class ShowTableStatsStmt extends ShowStmt {
.add("trigger")
.add("new_partition")
.add("user_inject")
.add("enable_auto_analyze")
.build();

private static final ImmutableList<String> PARTITION_TITLE_NAMES =
Expand Down Expand Up @@ -197,12 +198,12 @@ public long getTableId() {
return tableId;
}

public ShowResultSet constructResultSet(TableStatsMeta tableStatistic) {
public ShowResultSet constructResultSet(TableStatsMeta tableStatistic, TableIf table) {
if (indexName != null) {
return constructIndexResultSet(tableStatistic);
}
if (partitionNames == null) {
return constructTableResultSet(tableStatistic);
return constructTableResultSet(tableStatistic, table);
}
if (columnNames == null) {
return constructPartitionResultSet(tableStatistic);
Expand All @@ -215,7 +216,7 @@ public ShowResultSet constructEmptyResultSet() {
return new ShowResultSet(getMetaData(), new ArrayList<>());
}

public ShowResultSet constructResultSet(long rowCount) {
public ShowResultSet constructResultSet(TableIf table) {
List<List<String>> result = Lists.newArrayList();
if (partitionNames != null) {
// For partition, return empty result if table stats not exist.
Expand All @@ -224,17 +225,18 @@ public ShowResultSet constructResultSet(long rowCount) {
List<String> row = Lists.newArrayList();
row.add("");
row.add("");
row.add(String.valueOf(rowCount));
row.add(String.valueOf(table.getCachedRowCount()));
row.add("");
row.add("");
row.add("");
row.add("");
row.add("");
row.add(String.valueOf(table.autoAnalyzeEnabled()));
result.add(row);
return new ShowResultSet(getMetaData(), result);
}

public ShowResultSet constructTableResultSet(TableStatsMeta tableStatistic) {
public ShowResultSet constructTableResultSet(TableStatsMeta tableStatistic, TableIf table) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
if (tableStatistic == null) {
return new ShowResultSet(getMetaData(), new ArrayList<>());
Expand All @@ -253,6 +255,7 @@ public ShowResultSet constructTableResultSet(TableStatsMeta tableStatistic) {
row.add(tableStatistic.jobType.toString());
row.add(String.valueOf(tableStatistic.partitionChanged.get()));
row.add(String.valueOf(tableStatistic.userInjected));
row.add(table == null ? "N/A" : String.valueOf(table.autoAnalyzeEnabled()));
result.add(row);
return new ShowResultSet(getMetaData(), result);
}
Expand Down
38 changes: 37 additions & 1 deletion fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@
import org.apache.doris.cooldown.CooldownConfHandler;
import org.apache.doris.datasource.CatalogIf;
import org.apache.doris.datasource.CatalogMgr;
import org.apache.doris.datasource.ExternalCatalog;
import org.apache.doris.datasource.ExternalMetaCacheMgr;
import org.apache.doris.datasource.ExternalMetaIdMgr;
import org.apache.doris.datasource.InternalCatalog;
Expand Down Expand Up @@ -5286,7 +5287,8 @@ public void modifyTableProperties(Database db, OlapTable table, Map<String, Stri
.buildEnableSingleReplicaCompaction()
.buildTimeSeriesCompactionEmptyRowsetsThreshold()
.buildTimeSeriesCompactionLevelThreshold()
.buildTTLSeconds();
.buildTTLSeconds()
.buildAutoAnalyzeProperty();

// need to update partition info meta
for (Partition partition : table.getPartitions()) {
Expand All @@ -5313,10 +5315,17 @@ public void updateBinlogConfig(Database db, OlapTable table, BinlogConfig newBin

public void replayModifyTableProperty(short opCode, ModifyTablePropertyOperationLog info)
throws MetaNotFoundException {
String ctlName = info.getCtlName();
long dbId = info.getDbId();
long tableId = info.getTableId();
Map<String, String> properties = info.getProperties();

// Handle HMSExternalTable set auto analyze policy.
if (ctlName != null && !(InternalCatalog.INTERNAL_CATALOG_NAME.equalsIgnoreCase(ctlName))) {
setExternalTableAutoAnalyze(properties, info);
return;
}

Database db = getInternalCatalog().getDbOrMetaException(dbId);
OlapTable olapTable = (OlapTable) db.getTableOrMetaException(tableId, TableType.OLAP);
olapTable.writeLock();
Expand Down Expand Up @@ -5356,6 +5365,33 @@ public void replayModifyTableProperty(short opCode, ModifyTablePropertyOperation
}
}

private void setExternalTableAutoAnalyze(Map<String, String> properties, ModifyTablePropertyOperationLog info) {
if (properties.size() != 1) {
LOG.warn("External table property should contain exactly 1 entry.");
Jibing-Li marked this conversation as resolved.
Show resolved Hide resolved
return;
}
if (!properties.containsKey(PropertyAnalyzer.PROPERTIES_AUTO_ANALYZE_POLICY)) {
LOG.warn("External table property should only contain auto_analyze_policy");
return;
}
String value = properties.get(PropertyAnalyzer.PROPERTIES_AUTO_ANALYZE_POLICY);
if (!PropertyAnalyzer.ENABLE_AUTO_ANALYZE_POLICY.equalsIgnoreCase(value)
&& !PropertyAnalyzer.DISABLE_AUTO_ANALYZE_POLICY.equalsIgnoreCase(value)
&& !PropertyAnalyzer.USE_CATALOG_AUTO_ANALYZE_POLICY.equalsIgnoreCase(value)) {
LOG.warn("External table property should be 'enable', 'disable' or 'base_on_catalog'");
return;
}
try {
CatalogIf catalog = Env.getCurrentEnv().getCatalogMgr()
.getCatalogOrException(info.getCtlName(),
ctlName -> new DdlException("Unknown catalog " + ctlName));
value = value.equalsIgnoreCase(PropertyAnalyzer.USE_CATALOG_AUTO_ANALYZE_POLICY) ? null : value;
((ExternalCatalog) catalog).setAutoAnalyzePolicy(info.getDbName(), info.getTableName(), value);
} catch (Exception e) {
LOG.warn("Failed to replay external table set property.", e);
}
}

public void modifyDefaultDistributionBucketNum(Database db, OlapTable olapTable,
ModifyDistributionClause modifyDistributionClause)
throws DdlException {
Expand Down
15 changes: 15 additions & 0 deletions fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -3158,4 +3158,19 @@ public boolean isShadowIndex(long indexId) {
return false;
}
}

@Override
public boolean autoAnalyzeEnabled() {
if (tableProperty == null) {
return super.autoAnalyzeEnabled();
}
Map<String, String> properties = tableProperty.getProperties();
if (properties == null || !properties.containsKey(PropertyAnalyzer.PROPERTIES_AUTO_ANALYZE_POLICY)
|| properties.get(PropertyAnalyzer.PROPERTIES_AUTO_ANALYZE_POLICY)
.equalsIgnoreCase(PropertyAnalyzer.USE_CATALOG_AUTO_ANALYZE_POLICY)) {
return super.autoAnalyzeEnabled();
}
return properties.get(PropertyAnalyzer.PROPERTIES_AUTO_ANALYZE_POLICY)
.equalsIgnoreCase(PropertyAnalyzer.ENABLE_AUTO_ANALYZE_POLICY);
}
}
5 changes: 5 additions & 0 deletions fe/fe-core/src/main/java/org/apache/doris/catalog/Table.java
Original file line number Diff line number Diff line change
Expand Up @@ -634,4 +634,9 @@ public Set<Pair<String, String>> getColumnIndexPairs(Set<String> columns) {
public long getCachedRowCount() {
return getRowCount();
}

@Override
public boolean autoAnalyzeEnabled() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -561,4 +561,6 @@ default Set<String> getDistributionColumnNames() {
default boolean isPartitionedTable() {
return false;
}

boolean autoAnalyzeEnabled();
}
Loading
Loading