This is an automated email from the ASF dual-hosted git repository.
morningman pushed a commit to branch branch-2.1
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-2.1 by this push:
new 3ae3f9d6e1f [opt](catalog) support using loading cache for db/table
list in external catalog (#33610) (#34596)
3ae3f9d6e1f is described below
commit 3ae3f9d6e1f25fd78d7ae442b57ac29dedd201fe
Author: Mingyu Chen <[email protected]>
AuthorDate: Thu May 9 17:50:39 2024 +0800
[opt](catalog) support using loading cache for db/table list in external
catalog (#33610) (#34596)
bp #33610
---
.../main/java/org/apache/doris/common/Config.java | 2 +-
.../java/org/apache/doris/catalog/Database.java | 7 +-
.../java/org/apache/doris/catalog/DatabaseIf.java | 5 +-
.../org/apache/doris/catalog/JdbcResource.java | 22 +--
.../doris/catalog/MysqlCompatibleDatabase.java | 13 --
.../org/apache/doris/catalog/RefreshManager.java | 36 ++--
.../java/org/apache/doris/common/CacheFactory.java | 7 +-
.../apache/doris/common/util/PropertyAnalyzer.java | 9 +
.../java/org/apache/doris/common/util/Util.java | 20 ++
.../apache/doris/datasource/CatalogFactory.java | 9 +-
.../org/apache/doris/datasource/CatalogIf.java | 3 -
.../org/apache/doris/datasource/CatalogMgr.java | 26 ++-
.../apache/doris/datasource/ExternalCatalog.java | 208 ++++++++++++++-------
.../apache/doris/datasource/ExternalDatabase.java | 168 ++++++++++++-----
.../doris/datasource/ExternalMetaCacheMgr.java | 15 ++
.../doris/datasource/ExternalSchemaCache.java | 2 +-
.../apache/doris/datasource/InternalCatalog.java | 5 -
.../doris/datasource/es/EsExternalCatalog.java | 9 +-
.../doris/datasource/es/EsExternalDatabase.java | 2 +-
.../doris/datasource/hive/HMSExternalCatalog.java | 45 ++---
.../doris/datasource/hive/HMSExternalDatabase.java | 2 +-
.../doris/datasource/hive/HiveMetaStoreCache.java | 7 +-
.../datasource/hive/event/AlterTableEvent.java | 2 +-
.../doris/datasource/hive/event/InsertEvent.java | 2 +-
.../hudi/source/HudiCachedPartitionProcessor.java | 2 +-
.../datasource/iceberg/IcebergExternalCatalog.java | 5 -
.../iceberg/IcebergExternalDatabase.java | 2 +-
.../datasource/iceberg/IcebergMetadataCache.java | 4 +-
.../datasource/iceberg/IcebergMetadataOps.java | 7 +-
.../infoschema/ExternalInfoSchemaDatabase.java | 2 +-
.../infoschema/ExternalMysqlDatabase.java | 2 +-
.../doris/datasource/jdbc/JdbcExternalCatalog.java | 15 +-
.../datasource/jdbc/JdbcExternalDatabase.java | 2 +-
.../maxcompute/MaxComputeExternalDatabase.java | 2 +-
.../doris/datasource/metacache/MetaCache.java | 111 +++++++++++
.../datasource/paimon/PaimonExternalDatabase.java | 2 +-
.../doris/datasource/test/TestExternalCatalog.java | 24 ++-
.../datasource/test/TestExternalDatabase.java | 2 +-
.../java/org/apache/doris/qe/GlobalVariable.java | 2 +
.../apache/doris/service/FrontendServiceImpl.java | 6 +-
.../apache/doris/statistics/StatisticsCleaner.java | 12 +-
.../doris/statistics/query/DataBaseStats.java | 2 +-
.../doris/analysis/AlterCatalogPropsStmtTest.java | 10 +
.../org/apache/doris/common/CacheFactoryTest.java | 6 +-
.../apache/doris/datasource/CatalogMgrTest.java | 10 +-
.../doris/datasource/RefreshCatalogTest.java | 2 +-
.../datasource/iceberg/CreateIcebergTableTest.java | 12 +-
.../datasource/property/PropertyConverterTest.java | 28 +--
.../apache/doris/external/hms/HmsCatalogTest.java | 2 +
.../org/apache/doris/qe/HmsQueryCacheTest.java | 2 +
.../hive/test_hive_use_meta_cache.out | 77 ++++++++
.../org/apache/doris/regression/suite/Suite.groovy | 1 +
.../hive/test_hive_use_meta_cache.groovy | 102 ++++++++++
.../hive/write/test_hive_write_partitions.groovy | 2 +-
54 files changed, 785 insertions(+), 299 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 826b1ab8618..9973de61be6 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
@@ -1956,7 +1956,7 @@ public class Config extends ConfigBase {
* only for certain test type. E.g. only settting batch_size to small
* value for p0.
*/
- @ConfField(mutable = true, masterOnly = false)
+ @ConfField(mutable = true, masterOnly = false, options = {"p0"})
public static String fuzzy_test_type = "";
/**
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Database.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/Database.java
index fd709963a7b..548119dfb71 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Database.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Database.java
@@ -49,7 +49,6 @@ import java.io.DataOutput;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -416,6 +415,7 @@ public class Database extends MetaObject implements
Writable, DatabaseIf<Table>
}
}
+ @Override
public boolean registerTable(TableIf table) {
boolean result = true;
Table olapTable = (Table) table;
@@ -851,11 +851,6 @@ public class Database extends MetaObject implements
Writable, DatabaseIf<Table>
return null;
}
- @Override
- public Map<Long, TableIf> getIdToTable() {
- return new HashMap<>(idToTable);
- }
-
public void replayUpdateDbProperties(Map<String, String> properties) {
dbProperties.updateProperties(properties);
if (PropertyAnalyzer.hasBinlogConfig(properties)) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/DatabaseIf.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/DatabaseIf.java
index 6c0d46ffe98..3aae592dec0 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/DatabaseIf.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/DatabaseIf.java
@@ -31,7 +31,6 @@ import org.apache.logging.log4j.Logger;
import java.util.Arrays;
import java.util.List;
-import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
@@ -75,7 +74,7 @@ public interface DatabaseIf<T extends TableIf> {
List<T> getTables();
- default List<T> getTablesOrEmpty() {
+ default List<T> getTablesIgnoreException() {
try {
return getTables();
} catch (Exception e) {
@@ -281,6 +280,4 @@ public interface DatabaseIf<T extends TableIf> {
default long getLastUpdateTime() {
return -1L;
}
-
- Map<Long, TableIf> getIdToTable();
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/catalog/JdbcResource.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/JdbcResource.java
index 65bf7d308ff..95522503691 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/JdbcResource.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/JdbcResource.java
@@ -24,6 +24,7 @@ import org.apache.doris.common.DdlException;
import org.apache.doris.common.FeConstants;
import org.apache.doris.common.proc.BaseProcResult;
import org.apache.doris.common.util.Util;
+import org.apache.doris.datasource.ExternalCatalog;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
@@ -125,20 +126,8 @@ public class JdbcResource extends Resource {
CONNECTION_POOL_MAX_LIFE_TIME,
CONNECTION_POOL_MAX_WAIT_TIME,
CONNECTION_POOL_KEEP_ALIVE,
- TEST_CONNECTION
- ).build();
- private static final ImmutableList<String> OPTIONAL_PROPERTIES = new
ImmutableList.Builder<String>().add(
- ONLY_SPECIFIED_DATABASE,
- LOWER_CASE_META_NAMES,
- META_NAMES_MAPPING,
- INCLUDE_DATABASE_LIST,
- EXCLUDE_DATABASE_LIST,
- CONNECTION_POOL_MIN_SIZE,
- CONNECTION_POOL_MAX_SIZE,
- CONNECTION_POOL_MAX_LIFE_TIME,
- CONNECTION_POOL_MAX_WAIT_TIME,
- CONNECTION_POOL_KEEP_ALIVE,
- TEST_CONNECTION
+ TEST_CONNECTION,
+ ExternalCatalog.USE_META_CACHE
).build();
// The default value of optional properties
@@ -157,6 +146,8 @@ public class JdbcResource extends Resource {
OPTIONAL_PROPERTIES_DEFAULT_VALUE.put(CONNECTION_POOL_MAX_WAIT_TIME,
"5000");
OPTIONAL_PROPERTIES_DEFAULT_VALUE.put(CONNECTION_POOL_KEEP_ALIVE,
"false");
OPTIONAL_PROPERTIES_DEFAULT_VALUE.put(TEST_CONNECTION, "true");
+ OPTIONAL_PROPERTIES_DEFAULT_VALUE.put(ExternalCatalog.USE_META_CACHE,
+ String.valueOf(ExternalCatalog.DEFAULT_USE_META_CACHE));
}
// timeout for both connection and read. 10 seconds is long enough.
@@ -225,7 +216,7 @@ public class JdbcResource extends Resource {
@Override
public void applyDefaultProperties() {
- for (String s : OPTIONAL_PROPERTIES) {
+ for (String s : OPTIONAL_PROPERTIES_DEFAULT_VALUE.keySet()) {
if (!configs.containsKey(s)) {
configs.put(s, OPTIONAL_PROPERTIES_DEFAULT_VALUE.get(s));
}
@@ -487,3 +478,4 @@ public class JdbcResource extends Resource {
}
}
}
+
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/catalog/MysqlCompatibleDatabase.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/MysqlCompatibleDatabase.java
index 028fe186b2c..8bbdfe1d5fd 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/catalog/MysqlCompatibleDatabase.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/catalog/MysqlCompatibleDatabase.java
@@ -17,8 +17,6 @@
package org.apache.doris.catalog;
-import org.apache.doris.alter.Alter;
-import org.apache.doris.analysis.AlterTableStmt;
import org.apache.doris.analysis.CreateViewStmt;
import org.apache.doris.common.Pair;
@@ -43,17 +41,6 @@ public abstract class MysqlCompatibleDatabase extends
Database {
*/
protected abstract void initTables();
- /**
- * Currently, rename a table of InfoSchemaDb will throw exception
- * {@link Alter#processAlterTable(AlterTableStmt)}
- * so we follow this design.
- * @note: Rename a table of mysql database in MYSQL ls allowed.
- */
- @Override
- public boolean registerTable(TableIf table) {
- return super.registerTable(table);
- }
-
@Override
public void unregisterTable(String name) {
// Do nothing
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/catalog/RefreshManager.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/RefreshManager.java
index 39efce4c70f..d017ba7829f 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/RefreshManager.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/RefreshManager.java
@@ -41,6 +41,7 @@ import org.apache.logging.log4j.Logger;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@@ -108,10 +109,14 @@ public class RefreshManager {
private void refreshDbInternal(long catalogId, long dbId, boolean
invalidCache) {
ExternalCatalog catalog = (ExternalCatalog)
Env.getCurrentEnv().getCatalogMgr().getCatalog(catalogId);
- ExternalDatabase db = catalog.getDbForReplay(dbId);
- db.setUnInitialized(invalidCache);
- LOG.info("refresh database {} in catalog {} with invalidCache {}",
db.getFullName(), catalog.getName(),
- invalidCache);
+ Optional<ExternalDatabase<? extends ExternalTable>> db =
catalog.getDbForReplay(dbId);
+ // Database may not exist if 'use_meta_cache' is true.
+ // Because each FE fetch the meta data independently.
+ db.ifPresent(e -> {
+ e.setUnInitialized(invalidCache);
+ LOG.info("refresh database {} in catalog {} with invalidCache {}",
e.getFullName(),
+ catalog.getName(), invalidCache);
+ });
}
// Refresh table
@@ -163,13 +168,22 @@ public class RefreshManager {
LOG.warn("failed to find catalog replaying refresh table {}",
log.getCatalogId());
return;
}
- ExternalDatabase db = catalog.getDbForReplay(log.getDbId());
- TableIf table = db.getTableForReplay(log.getTableId());
- refreshTableInternal(catalog, db, table, log.getLastUpdateTime());
+ Optional<ExternalDatabase<? extends ExternalTable>> db =
catalog.getDbForReplay(log.getDbId());
+ // See comment in refreshDbInternal for why db and table may be null.
+ if (!db.isPresent()) {
+ LOG.warn("failed to find db replaying refresh table {}",
log.getDbId());
+ return;
+ }
+ Optional<? extends ExternalTable> table =
db.get().getTableForReplay(log.getTableId());
+ if (!table.isPresent()) {
+ LOG.warn("failed to find table replaying refresh table {}",
log.getTableId());
+ return;
+ }
+ refreshTableInternal(catalog, db.get(), table.get(),
log.getLastUpdateTime());
}
public void refreshExternalTableFromEvent(String catalogName, String
dbName, String tableName,
- long updateTime, boolean ignoreIfNotExists) throws DdlException {
+ long updateTime) throws DdlException {
CatalogIf catalog =
Env.getCurrentEnv().getCatalogMgr().getCatalog(catalogName);
if (catalog == null) {
throw new DdlException("No catalog found with name: " +
catalogName);
@@ -179,17 +193,11 @@ public class RefreshManager {
}
DatabaseIf db = catalog.getDbNullable(dbName);
if (db == null) {
- if (!ignoreIfNotExists) {
- throw new DdlException("Database " + dbName + " does not exist
in catalog " + catalog.getName());
- }
return;
}
TableIf table = db.getTableNullable(tableName);
if (table == null) {
- if (!ignoreIfNotExists) {
- throw new DdlException("Table " + tableName + " does not exist
in db " + dbName);
- }
return;
}
refreshTableInternal(catalog, db, table, updateTime);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/CacheFactory.java
b/fe/fe-core/src/main/java/org/apache/doris/common/CacheFactory.java
index fbb004e5c99..50f46647975 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/common/CacheFactory.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/CacheFactory.java
@@ -22,6 +22,7 @@ import com.github.benmanes.caffeine.cache.AsyncLoadingCache;
import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
+import com.github.benmanes.caffeine.cache.RemovalListener;
import com.github.benmanes.caffeine.cache.Ticker;
import org.jetbrains.annotations.NotNull;
@@ -74,9 +75,13 @@ public class CacheFactory {
}
// Build a loading cache, with executor, it will use given executor for
refresh
- public <K, V> LoadingCache<K, V> buildCache(CacheLoader<K, V> cacheLoader,
ExecutorService executor) {
+ public <K, V> LoadingCache<K, V> buildCache(CacheLoader<K, V> cacheLoader,
+ RemovalListener<K, V> removalListener, ExecutorService executor) {
Caffeine<Object, Object> builder = buildWithParams();
builder.executor(executor);
+ if (removalListener != null) {
+ builder.removalListener(removalListener);
+ }
return builder.build(cacheLoader);
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/common/util/PropertyAnalyzer.java
b/fe/fe-core/src/main/java/org/apache/doris/common/util/PropertyAnalyzer.java
index e411e992e97..ba4434349cb 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/common/util/PropertyAnalyzer.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/common/util/PropertyAnalyzer.java
@@ -35,6 +35,7 @@ import org.apache.doris.common.Config;
import org.apache.doris.common.DdlException;
import org.apache.doris.datasource.CatalogIf;
import org.apache.doris.datasource.CatalogMgr;
+import org.apache.doris.datasource.ExternalCatalog;
import org.apache.doris.policy.Policy;
import org.apache.doris.policy.StoragePolicy;
import org.apache.doris.resource.Tag;
@@ -1348,6 +1349,14 @@ public class PropertyAnalyzer {
throw new AnalysisException("failed to find class " + acClass,
e);
}
}
+
+ if (isAlter) {
+ // The 'use_meta_cache' property can not be modified
+ if (properties.containsKey(ExternalCatalog.USE_META_CACHE)) {
+ throw new AnalysisException("Can not modify property " +
ExternalCatalog.USE_META_CACHE
+ + ". You need to create a new Catalog with the
property.");
+ }
+ }
}
public static Map<String, String> rewriteReplicaAllocationProperties(
diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java
b/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java
index c454c6cab5c..be3e711f453 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java
@@ -44,6 +44,9 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URL;
import java.net.URLConnection;
+import java.nio.ByteBuffer;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collections;
@@ -651,4 +654,21 @@ public class Util {
p.printStackTrace(pw);
return sw.toString();
}
+
+ public static long sha256long(String str) {
+ try {
+ MessageDigest digest = MessageDigest.getInstance("SHA-256");
+ byte[] hash = digest.digest(str.getBytes());
+ ByteBuffer buffer = ByteBuffer.wrap(hash);
+ return buffer.getLong();
+ } catch (NoSuchAlgorithmException e) {
+ return str.hashCode();
+ }
+ }
+
+ // Only used for external table's id generation
+ // And the table's id must >=0, see DescriptorTable.toThrift()
+ public static long genTableIdByName(String tblName) {
+ return Math.abs(sha256long(tblName));
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/CatalogFactory.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/CatalogFactory.java
index 264477d22a6..23558ce5768 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/datasource/CatalogFactory.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/CatalogFactory.java
@@ -142,10 +142,13 @@ public class CatalogFactory {
default:
throw new DdlException("Unknown catalog type: " + catalogType);
}
+
+ // set some default properties if missing when creating catalog.
+ // both replaying the creating logic will call this method.
+ catalog.setDefaultPropsIfMissing(isReplay);
+
if (!isReplay) {
- // set some default properties when creating catalog.
- // do not call this method when replaying edit log. Because we
need to keey the original properties.
- catalog.setDefaultPropsWhenCreating(isReplay);
+ catalog.checkWhenCreating();
// This will check if the customized access controller can be
created successfully.
// If failed, it will throw exception and the catalog will not be
created.
try {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/CatalogIf.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/CatalogIf.java
index 44dba04157e..072597deb55 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/datasource/CatalogIf.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/CatalogIf.java
@@ -40,7 +40,6 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import javax.annotation.Nullable;
@@ -184,8 +183,6 @@ public interface CatalogIf<T extends DatabaseIf> {
boolean enableAutoAnalyze();
- ConcurrentHashMap<Long, DatabaseIf> getIdToDb();
-
void createDb(CreateDbStmt stmt) throws DdlException;
void dropDb(DropDbStmt stmt) throws DdlException;
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/CatalogMgr.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/CatalogMgr.java
index 56b390bc7d3..48fa0cc14cf 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/datasource/CatalogMgr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/CatalogMgr.java
@@ -43,6 +43,7 @@ import org.apache.doris.common.io.Text;
import org.apache.doris.common.io.Writable;
import org.apache.doris.common.util.PrintableMap;
import org.apache.doris.common.util.TimeUtils;
+import org.apache.doris.common.util.Util;
import org.apache.doris.datasource.hive.HMSExternalCatalog;
import org.apache.doris.datasource.hive.HMSExternalTable;
import org.apache.doris.mysql.privilege.PrivPredicate;
@@ -66,6 +67,7 @@ import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -587,11 +589,11 @@ public class CatalogMgr implements Writable,
GsonPostProcessable {
if (catalog == null) {
return;
}
- ExternalDatabase db = catalog.getDbForReplay(log.getDbId());
- if (db == null) {
+ Optional<ExternalDatabase<? extends ExternalTable>> db =
catalog.getDbForReplay(log.getDbId());
+ if (!db.isPresent()) {
return;
}
- db.replayInitDb(log, catalog);
+ db.get().replayInitDb(log, catalog);
}
public void unregisterExternalTable(String dbName, String tableName,
String catalogName, boolean ignoreIfExists)
@@ -663,7 +665,13 @@ public class CatalogMgr implements Writable,
GsonPostProcessable {
}
return;
}
- long tblId =
Env.getCurrentEnv().getExternalMetaIdMgr().getTblId(catalog.getId(), dbName,
tableName);
+ long tblId;
+ HMSExternalCatalog hmsCatalog = (HMSExternalCatalog) catalog;
+ if (hmsCatalog.getUseMetaCache().get()) {
+ tblId = Util.genTableIdByName(tableName);
+ } else {
+ tblId =
Env.getCurrentEnv().getExternalMetaIdMgr().getTblId(catalog.getId(), dbName,
tableName);
+ }
// -1L means it will be dropped later, ignore
if (tblId == ExternalMetaIdMgr.META_ID_FOR_NOT_EXISTS) {
return;
@@ -715,13 +723,19 @@ public class CatalogMgr implements Writable,
GsonPostProcessable {
return;
}
- long dbId =
Env.getCurrentEnv().getExternalMetaIdMgr().getDbId(catalog.getId(), dbName);
+ HMSExternalCatalog hmsCatalog = (HMSExternalCatalog) catalog;
+ long dbId;
+ if (hmsCatalog.getUseMetaCache().get()) {
+ dbId =
Env.getCurrentEnv().getExternalMetaIdMgr().getDbId(catalog.getId(), dbName);
+ } else {
+ dbId = Util.genTableIdByName(dbName);
+ }
// -1L means it will be dropped later, ignore
if (dbId == ExternalMetaIdMgr.META_ID_FOR_NOT_EXISTS) {
return;
}
- ((HMSExternalCatalog) catalog).registerDatabase(dbId, dbName);
+ hmsCatalog.registerDatabase(dbId, dbName);
}
public void addExternalPartitions(String catalogName, String dbName,
String tableName,
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalCatalog.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalCatalog.java
index 6d5ae985fef..72eacbb1de5 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalCatalog.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalCatalog.java
@@ -30,6 +30,7 @@ import org.apache.doris.catalog.MysqlDb;
import org.apache.doris.catalog.Resource;
import org.apache.doris.catalog.TableIf;
import org.apache.doris.cluster.ClusterNamespace;
+import org.apache.doris.common.Config;
import org.apache.doris.common.DdlException;
import org.apache.doris.common.UserException;
import org.apache.doris.common.Version;
@@ -44,6 +45,7 @@ import
org.apache.doris.datasource.infoschema.ExternalInfoSchemaDatabase;
import org.apache.doris.datasource.infoschema.ExternalMysqlDatabase;
import org.apache.doris.datasource.jdbc.JdbcExternalDatabase;
import org.apache.doris.datasource.maxcompute.MaxComputeExternalDatabase;
+import org.apache.doris.datasource.metacache.MetaCache;
import org.apache.doris.datasource.operations.ExternalMetadataOps;
import org.apache.doris.datasource.paimon.PaimonExternalDatabase;
import org.apache.doris.datasource.property.PropertyConverter;
@@ -54,9 +56,11 @@ import org.apache.doris.qe.ConnectContext;
import org.apache.doris.qe.MasterCatalogExecutor;
import org.apache.doris.transaction.TransactionManager;
+import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import org.apache.commons.lang3.NotImplementedException;
@@ -65,6 +69,7 @@ import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hdfs.HdfsConfiguration;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.DataInput;
@@ -77,19 +82,24 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.OptionalLong;
+import java.util.Set;
+import java.util.stream.Collectors;
/**
* The abstract class for all types of external catalogs.
*/
@Data
public abstract class ExternalCatalog
- implements CatalogIf<ExternalDatabase<? extends ExternalTable>>,
Writable, GsonPostProcessable {
+ implements CatalogIf<ExternalDatabase<? extends ExternalTable>>,
Writable, GsonPostProcessable {
private static final Logger LOG =
LogManager.getLogger(ExternalCatalog.class);
public static final String ENABLE_AUTO_ANALYZE = "enable.auto.analyze";
public static final String DORIS_VERSION = "doris.version";
public static final String DORIS_VERSION_VALUE =
Version.DORIS_BUILD_VERSION + "-" + Version.DORIS_BUILD_SHORT_HASH;
+ public static final String USE_META_CACHE = "use_meta_cache";
+ // Set default value to false to be compatible with older version meta
data.
+ public static final boolean DEFAULT_USE_META_CACHE = false;
// Unique id of this catalog, will be assigned after catalog is loaded.
@SerializedName(value = "id")
@@ -123,6 +133,9 @@ public abstract class ExternalCatalog
private byte[] propLock = new byte[0];
private Map<String, String> convertedProperties = null;
+ protected Optional<Boolean> useMetaCache = Optional.empty();
+ protected MetaCache<ExternalDatabase<? extends ExternalTable>> metaCache;
+
public ExternalCatalog() {
}
@@ -130,7 +143,7 @@ public abstract class ExternalCatalog
this.id = catalogId;
this.name = name;
this.logType = logType;
- this.comment = com.google.common.base.Strings.nullToEmpty(comment);
+ this.comment = Strings.nullToEmpty(comment);
}
public Configuration getConfiguration() {
@@ -142,11 +155,6 @@ public abstract class ExternalCatalog
return conf;
}
- // only for test
- public void setInitialized() {
- initialized = true;
- }
-
/**
* set some default properties when creating catalog
* @return list of database names in this catalog
@@ -160,8 +168,21 @@ public abstract class ExternalCatalog
}
}
- public void setDefaultPropsWhenCreating(boolean isReplay) throws
DdlException {
+ // Will be called when creating catalog(so when as replaying)
+ // to add some default properties if missing.
+ public void setDefaultPropsIfMissing(boolean isReplay) {
+ if (catalogProperty.getOrDefault(USE_META_CACHE, "").isEmpty()) {
+ // If not setting USE_META_CACHE in replay logic,
+ // set default value to false to be compatible with older version
meta data.
+ catalogProperty.addProperty(USE_META_CACHE, isReplay ? "false" :
String.valueOf(DEFAULT_USE_META_CACHE));
+ }
+ useMetaCache = Optional.of(
+ Boolean.valueOf(catalogProperty.getOrDefault(USE_META_CACHE,
String.valueOf(DEFAULT_USE_META_CACHE))));
+ }
+ // Will be called when creating catalog(not replaying).
+ // Subclass can override this method to do some check when creating
catalog.
+ public void checkWhenCreating() throws DdlException {
}
/**
@@ -204,19 +225,36 @@ public abstract class ExternalCatalog
public final synchronized void makeSureInitialized() {
initLocalObjects();
if (!initialized) {
- if (!Env.getCurrentEnv().isMaster()) {
- // Forward to master and wait the journal to replay.
- int waitTimeOut = ConnectContext.get() == null ? 300 :
ConnectContext.get().getExecTimeout();
- MasterCatalogExecutor remoteExecutor = new
MasterCatalogExecutor(waitTimeOut * 1000);
- try {
- remoteExecutor.forward(id, -1);
- } catch (Exception e) {
- Util.logAndThrowRuntimeException(LOG,
- String.format("failed to forward init catalog %s
operation to master.", name), e);
+ if (useMetaCache.get()) {
+ if (metaCache != null) {
+ metaCache.invalidateAll();
+ } else {
+ metaCache =
Env.getCurrentEnv().getExtMetaCacheMgr().buildMetaCache(
+ name,
+ OptionalLong.of(86400L),
+
OptionalLong.of(Config.external_cache_expire_time_minutes_after_access * 60L),
+ Config.max_hive_table_cache_num,
+ ignored -> getFilteredDatabaseNames(),
+ dbName -> Optional.ofNullable(
+ buildDbForInit(dbName,
Util.genTableIdByName(dbName), logType)),
+ (key, value, cause) -> value.ifPresent(v ->
v.setUnInitialized(invalidCacheInInit)));
+ }
+ setLastUpdateTime(System.currentTimeMillis());
+ } else {
+ if (!Env.getCurrentEnv().isMaster()) {
+ // Forward to master and wait the journal to replay.
+ int waitTimeOut = ConnectContext.get() == null ? 300 :
ConnectContext.get().getExecTimeout();
+ MasterCatalogExecutor remoteExecutor = new
MasterCatalogExecutor(waitTimeOut * 1000);
+ try {
+ remoteExecutor.forward(id, -1);
+ } catch (Exception e) {
+ Util.logAndThrowRuntimeException(LOG,
+ String.format("failed to forward init catalog
%s operation to master.", name), e);
+ }
+ return;
}
- return;
+ init();
}
- init();
initialized = true;
}
}
@@ -283,18 +321,13 @@ public abstract class ExternalCatalog
}
// init schema related objects
- protected void init() {
+ private void init() {
Map<String, Long> tmpDbNameToId = Maps.newConcurrentMap();
Map<Long, ExternalDatabase<? extends ExternalTable>> tmpIdToDb =
Maps.newConcurrentMap();
InitCatalogLog initCatalogLog = new InitCatalogLog();
initCatalogLog.setCatalogId(id);
initCatalogLog.setType(logType);
- List<String> allDatabases = Lists.newArrayList(listDatabaseNames());
-
- allDatabases.remove(InfoSchemaDb.DATABASE_NAME);
- allDatabases.add(InfoSchemaDb.DATABASE_NAME);
- allDatabases.remove(MysqlDb.DATABASE_NAME);
- allDatabases.add(MysqlDb.DATABASE_NAME);
+ List<String> allDatabases = getFilteredDatabaseNames();
Map<String, Boolean> includeDatabaseMap = getIncludeDatabaseMap();
Map<String, Boolean> excludeDatabaseMap = getExcludeDatabaseMap();
for (String dbName : allDatabases) {
@@ -318,7 +351,7 @@ public abstract class ExternalCatalog
} else {
dbId = Env.getCurrentEnv().getNextId();
tmpDbNameToId.put(dbName, dbId);
- ExternalDatabase<? extends ExternalTable> db =
getDbForInit(dbName, dbId, logType);
+ ExternalDatabase<? extends ExternalTable> db =
buildDbForInit(dbName, dbId, logType);
tmpIdToDb.put(dbId, db);
initCatalogLog.addCreateDb(dbId, dbName);
}
@@ -331,6 +364,16 @@ public abstract class ExternalCatalog
Env.getCurrentEnv().getEditLog().logInitCatalog(initCatalogLog);
}
+ @NotNull
+ private List<String> getFilteredDatabaseNames() {
+ List<String> allDatabases = Lists.newArrayList(listDatabaseNames());
+ allDatabases.remove(InfoSchemaDb.DATABASE_NAME);
+ allDatabases.add(InfoSchemaDb.DATABASE_NAME);
+ allDatabases.remove(MysqlDb.DATABASE_NAME);
+ allDatabases.add(MysqlDb.DATABASE_NAME);
+ return allDatabases;
+ }
+
public void onRefresh(boolean invalidCache) {
this.objectCreated = false;
this.initialized = false;
@@ -382,12 +425,18 @@ public abstract class ExternalCatalog
}
/**
+ * Different from 'listDatabases()', this method will return dbnames from
cache.
+ * while 'listDatabases()' will return dbnames from remote datasource.
* @return names of database in this catalog.
*/
@Override
public List<String> getDbNames() {
makeSureInitialized();
- return new ArrayList<>(dbNameToId.keySet());
+ if (useMetaCache.get()) {
+ return metaCache.listNames();
+ } else {
+ return new ArrayList<>(dbNameToId.keySet());
+ }
}
@Override
@@ -404,14 +453,10 @@ public abstract class ExternalCatalog
}
}
+ @Override
public TableName getTableNameByTableId(Long tableId) {
- for (DatabaseIf<?> db : idToDb.values()) {
- TableIf table = db.getTableNullable(tableId);
- if (table != null) {
- return new TableName(getName(), db.getFullName(),
table.getName());
- }
- }
- return null;
+ throw new UnsupportedOperationException("External catalog does not
support getTableNameByTableId() method."
+ + ", table id: " + tableId);
}
@Override
@@ -432,21 +477,23 @@ public abstract class ExternalCatalog
return null;
}
String realDbName = ClusterNamespace.getNameFromFullName(dbName);
- if (dbNameToId.containsKey(realDbName)) {
- return idToDb.get(dbNameToId.get(realDbName));
+
+ // information_schema db name is case-insensitive.
+ // So, we first convert it to standard database name.
+ if (realDbName.equalsIgnoreCase(InfoSchemaDb.DATABASE_NAME)) {
+ realDbName = InfoSchemaDb.DATABASE_NAME;
+ } else if (realDbName.equalsIgnoreCase(MysqlDb.DATABASE_NAME)) {
+ realDbName = MysqlDb.DATABASE_NAME;
+ }
+
+ if (useMetaCache.get()) {
+ return metaCache.getMetaObj(realDbName).orElse(null);
} else {
- // This maybe a information_schema db request, and
information_schema db name is case insensitive.
- // So, we first extract db name to check if it is
information_schema.
- // Then we reassemble the origin cluster name with lower case db
name,
- // and finally get information_schema db from the name map.
- if (realDbName.equalsIgnoreCase(InfoSchemaDb.DATABASE_NAME)) {
- return idToDb.get(dbNameToId.get(InfoSchemaDb.DATABASE_NAME));
- }
- if (realDbName.equalsIgnoreCase(MysqlDb.DATABASE_NAME)) {
- return idToDb.get(dbNameToId.get(MysqlDb.DATABASE_NAME));
+ if (dbNameToId.containsKey(realDbName)) {
+ return idToDb.get(dbNameToId.get(realDbName));
}
+ return null;
}
- return null;
}
@Nullable
@@ -458,13 +505,22 @@ public abstract class ExternalCatalog
LOG.warn("failed to get db {} in catalog {}", dbId, name, e);
return null;
}
- return idToDb.get(dbId);
+
+ if (useMetaCache.get()) {
+ return metaCache.getMetaObjById(dbId).get();
+ } else {
+ return idToDb.get(dbId);
+ }
}
@Override
public List<Long> getDbIds() {
makeSureInitialized();
- return Lists.newArrayList(dbNameToId.values());
+ if (useMetaCache.get()) {
+ return
getAllDbs().stream().map(DatabaseIf::getId).collect(Collectors.toList());
+ } else {
+ return Lists.newArrayList(dbNameToId.values());
+ }
}
@Override
@@ -528,14 +584,18 @@ public abstract class ExternalCatalog
Map<String, Long> tmpDbNameToId = Maps.newConcurrentMap();
Map<Long, ExternalDatabase<? extends ExternalTable>> tmpIdToDb =
Maps.newConcurrentMap();
for (int i = 0; i < log.getRefreshCount(); i++) {
- ExternalDatabase<? extends ExternalTable> db =
getDbForReplay(log.getRefreshDbIds().get(i));
- db.setUnInitialized(invalidCacheInInit);
- tmpDbNameToId.put(db.getFullName(), db.getId());
- tmpIdToDb.put(db.getId(), db);
+ Optional<ExternalDatabase<? extends ExternalTable>> db =
getDbForReplay(log.getRefreshDbIds().get(i));
+ // Should not return null.
+ // Because replyInitCatalog can only be called when
`use_meta_cache` is false.
+ // And if `use_meta_cache` is false, getDbForReplay() will not
return null
+ Preconditions.checkNotNull(db.get());
+ db.get().setUnInitialized(invalidCacheInInit);
+ tmpDbNameToId.put(db.get().getFullName(), db.get().getId());
+ tmpIdToDb.put(db.get().getId(), db.get());
}
for (int i = 0; i < log.getCreateCount(); i++) {
ExternalDatabase<? extends ExternalTable> db =
- getDbForInit(log.getCreateDbNames().get(i),
log.getCreateDbIds().get(i), log.getType());
+ buildDbForInit(log.getCreateDbNames().get(i),
log.getCreateDbIds().get(i), log.getType());
if (db != null) {
tmpDbNameToId.put(db.getFullName(), db.getId());
tmpIdToDb.put(db.getId(), db);
@@ -547,12 +607,19 @@ public abstract class ExternalCatalog
initialized = true;
}
- public ExternalDatabase<? extends ExternalTable> getDbForReplay(long
dbId) {
- return idToDb.get(dbId);
+ public Optional<ExternalDatabase<? extends ExternalTable>>
getDbForReplay(long dbId) {
+ if (useMetaCache.get()) {
+ if (!isInitialized()) {
+ return Optional.empty();
+ }
+ return metaCache.getMetaObjById(dbId);
+ } else {
+ return Optional.ofNullable(idToDb.get(dbId));
+ }
}
- protected ExternalDatabase<? extends ExternalTable> getDbForInit(String
dbName, long dbId,
-
InitCatalogLog.Type logType) {
+ protected ExternalDatabase<? extends ExternalTable> buildDbForInit(String
dbName, long dbId,
+ InitCatalogLog.Type logType) {
if (dbName.equals(InfoSchemaDb.DATABASE_NAME)) {
return new ExternalInfoSchemaDatabase(this, dbId);
}
@@ -614,6 +681,8 @@ public abstract class ExternalCatalog
}
}
this.propLock = new byte[0];
+ this.initialized = false;
+ setDefaultPropsIfMissing(true);
}
public void addDatabaseForTest(ExternalDatabase<? extends ExternalTable>
db) {
@@ -722,10 +791,24 @@ public abstract class ExternalCatalog
return null;
}
+ // ATTN: this method only return all cached databases.
+ // will not visit remote datasource's metadata
@Override
public Collection<DatabaseIf<? extends TableIf>> getAllDbs() {
makeSureInitialized();
- return new HashSet<>(idToDb.values());
+ if (useMetaCache.get()) {
+ Set<DatabaseIf<? extends TableIf>> dbs = Sets.newHashSet();
+ List<String> dbNames = getDbNames();
+ for (String dbName : dbNames) {
+ ExternalDatabase<? extends ExternalTable> db =
getDbNullable(dbName);
+ if (db != null) {
+ dbs.add(db);
+ }
+ }
+ return dbs;
+ } else {
+ return new HashSet<>(idToDb.values());
+ }
}
@Override
@@ -740,9 +823,4 @@ public abstract class ExternalCatalog
}
return ret;
}
-
- @Override
- public ConcurrentHashMap<Long, DatabaseIf> getIdToDb() {
- return new ConcurrentHashMap<>(idToDb);
- }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalDatabase.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalDatabase.java
index 3308b04968f..43c24b5ebd5 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalDatabase.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalDatabase.java
@@ -23,6 +23,7 @@ import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.InfoSchemaDb;
import org.apache.doris.catalog.MysqlDb;
import org.apache.doris.catalog.TableIf;
+import org.apache.doris.common.Config;
import org.apache.doris.common.DdlException;
import org.apache.doris.common.MetaNotFoundException;
import org.apache.doris.common.io.Text;
@@ -32,6 +33,7 @@ import
org.apache.doris.datasource.infoschema.ExternalInfoSchemaDatabase;
import org.apache.doris.datasource.infoschema.ExternalInfoSchemaTable;
import org.apache.doris.datasource.infoschema.ExternalMysqlDatabase;
import org.apache.doris.datasource.infoschema.ExternalMysqlTable;
+import org.apache.doris.datasource.metacache.MetaCache;
import org.apache.doris.persist.gson.GsonPostProcessable;
import org.apache.doris.persist.gson.GsonUtils;
import org.apache.doris.qe.ConnectContext;
@@ -50,9 +52,10 @@ import org.apache.logging.log4j.Logger;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
+import java.util.OptionalLong;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -86,6 +89,8 @@ public abstract class ExternalDatabase<T extends
ExternalTable>
protected ExternalCatalog extCatalog;
protected boolean invalidCacheInInit = true;
+ private MetaCache<T> metaCache;
+
/**
* Create external database.
*
@@ -125,19 +130,37 @@ public abstract class ExternalDatabase<T extends
ExternalTable>
public final synchronized void makeSureInitialized() {
extCatalog.makeSureInitialized();
if (!initialized) {
- if (!Env.getCurrentEnv().isMaster()) {
- // Forward to master and wait the journal to replay.
- int waitTimeOut = ConnectContext.get() == null ? 300 :
ConnectContext.get().getExecTimeout();
- MasterCatalogExecutor remoteExecutor = new
MasterCatalogExecutor(waitTimeOut * 1000);
- try {
- remoteExecutor.forward(extCatalog.getId(), id);
- } catch (Exception e) {
- Util.logAndThrowRuntimeException(LOG,
- String.format("failed to forward init external db
%s operation to master", name), e);
+ if (extCatalog.getUseMetaCache().get()) {
+ if (metaCache != null) {
+ metaCache.invalidateAll();
+ } else {
+ metaCache =
Env.getCurrentEnv().getExtMetaCacheMgr().buildMetaCache(
+ name,
+ OptionalLong.of(86400L),
+
OptionalLong.of(Config.external_cache_expire_time_minutes_after_access * 60L),
+ Config.max_hive_table_cache_num,
+ ignored -> listTableNames(),
+ tableName -> Optional.ofNullable(
+ buildTableForInit(tableName,
Util.genTableIdByName(tableName), extCatalog)),
+ (key, value, cause) ->
value.ifPresent(ExternalTable::unsetObjectCreated));
}
- return;
+ setLastUpdateTime(System.currentTimeMillis());
+ } else {
+ if (!Env.getCurrentEnv().isMaster()) {
+ // Forward to master and wait the journal to replay.
+ int waitTimeOut = ConnectContext.get() == null ? 300 :
ConnectContext.get().getExecTimeout();
+ MasterCatalogExecutor remoteExecutor = new
MasterCatalogExecutor(waitTimeOut * 1000);
+ try {
+ remoteExecutor.forward(extCatalog.getId(), id);
+ } catch (Exception e) {
+ Util.logAndThrowRuntimeException(LOG,
+ String.format("failed to forward init external
db %s operation to master", name), e);
+ }
+ return;
+ }
+ init();
}
- init();
+ initialized = true;
}
}
@@ -145,20 +168,20 @@ public abstract class ExternalDatabase<T extends
ExternalTable>
Map<String, Long> tmpTableNameToId = Maps.newConcurrentMap();
Map<Long, T> tmpIdToTbl = Maps.newConcurrentMap();
for (int i = 0; i < log.getRefreshCount(); i++) {
- T table = getTableForReplay(log.getRefreshTableIds().get(i));
+ Optional<T> table =
getTableForReplay(log.getRefreshTableIds().get(i));
// When upgrade cluster with this pr:
https://github.com/apache/doris/pull/27666
// Maybe there are some create table events will be skipped
// if the cluster has any hms catalog(s) with hms event listener
enabled.
// So we need add a validation here to avoid table(s) not found,
this is just a temporary solution
// because later we will remove all the logics about
InitCatalogLog/InitDatabaseLog.
- if (table != null) {
- table.unsetObjectCreated();
- tmpTableNameToId.put(table.getName(), table.getId());
- tmpIdToTbl.put(table.getId(), table);
+ if (table.isPresent()) {
+ table.get().unsetObjectCreated();
+ tmpTableNameToId.put(table.get().getName(),
table.get().getId());
+ tmpIdToTbl.put(table.get().getId(), table.get());
}
}
for (int i = 0; i < log.getCreateCount(); i++) {
- T table = newExternalTable(log.getCreateTableNames().get(i),
log.getCreateTableIds().get(i), catalog);
+ T table = buildTableForInit(log.getCreateTableNames().get(i),
log.getCreateTableIds().get(i), catalog);
tmpTableNameToId.put(table.getName(), table.getId());
tmpIdToTbl.put(table.getId(), table);
}
@@ -168,19 +191,12 @@ public abstract class ExternalDatabase<T extends
ExternalTable>
initialized = true;
}
- protected void init() {
+ private void init() {
InitDatabaseLog initDatabaseLog = new InitDatabaseLog();
initDatabaseLog.setType(dbLogType);
initDatabaseLog.setCatalogId(extCatalog.getId());
initDatabaseLog.setDbId(id);
- List<String> tableNames;
- if (name.equals(InfoSchemaDb.DATABASE_NAME)) {
- tableNames = ExternalInfoSchemaDatabase.listTableNames();
- } else if (name.equals(MysqlDb.DATABASE_NAME)) {
- tableNames = ExternalMysqlDatabase.listTableNames();
- } else {
- tableNames = extCatalog.listTableNames(null, name);
- }
+ List<String> tableNames = listTableNames();
if (tableNames != null) {
Map<String, Long> tmpTableNameToId = Maps.newConcurrentMap();
Map<Long, T> tmpIdToTbl = Maps.newHashMap();
@@ -196,7 +212,7 @@ public abstract class ExternalDatabase<T extends
ExternalTable>
} else {
tblId = Env.getCurrentEnv().getNextId();
tmpTableNameToId.put(tableName, tblId);
- T table = newExternalTable(tableName, tblId, extCatalog);
+ T table = buildTableForInit(tableName, tblId, extCatalog);
tmpIdToTbl.put(tblId, table);
initDatabaseLog.addCreateTable(tblId, tableName);
}
@@ -207,14 +223,32 @@ public abstract class ExternalDatabase<T extends
ExternalTable>
lastUpdateTime = System.currentTimeMillis();
initDatabaseLog.setLastUpdateTime(lastUpdateTime);
- initialized = true;
Env.getCurrentEnv().getEditLog().logInitExternalDb(initDatabaseLog);
}
- protected abstract T newExternalTable(String tableName, long tblId,
ExternalCatalog catalog);
+ private List<String> listTableNames() {
+ List<String> tableNames;
+ if (name.equals(InfoSchemaDb.DATABASE_NAME)) {
+ tableNames = ExternalInfoSchemaDatabase.listTableNames();
+ } else if (name.equals(MysqlDb.DATABASE_NAME)) {
+ tableNames = ExternalMysqlDatabase.listTableNames();
+ } else {
+ tableNames = extCatalog.listTableNames(null, name);
+ }
+ return tableNames;
+ }
+
+ protected abstract T buildTableForInit(String tableName, long tblId,
ExternalCatalog catalog);
- public T getTableForReplay(long tableId) {
- return idToTbl.get(tableId);
+ public Optional<T> getTableForReplay(long tableId) {
+ if (extCatalog.getUseMetaCache().get()) {
+ if (!isInitialized()) {
+ return Optional.empty();
+ }
+ return metaCache.getMetaObjById(tableId);
+ } else {
+ return Optional.ofNullable(idToTbl.get(tableId));
+ }
}
@Override
@@ -288,10 +322,23 @@ public abstract class ExternalDatabase<T extends
ExternalTable>
return extCatalog.tableExist(ConnectContext.get().getSessionContext(),
name, tableName);
}
+ // ATTN: this method only returned cached tables.
@Override
public List<T> getTables() {
makeSureInitialized();
- return Lists.newArrayList(idToTbl.values());
+ if (extCatalog.getUseMetaCache().get()) {
+ List<T> tables = Lists.newArrayList();
+ Set<String> tblNames = getTableNamesWithLock();
+ for (String tblName : tblNames) {
+ T tbl = getTableNullable(tblName);
+ if (tbl != null) {
+ tables.add(tbl);
+ }
+ }
+ return tables;
+ } else {
+ return Lists.newArrayList(idToTbl.values());
+ }
}
@Override
@@ -312,22 +359,34 @@ public abstract class ExternalDatabase<T extends
ExternalTable>
@Override
public Set<String> getTableNamesWithLock() {
makeSureInitialized();
- return Sets.newHashSet(tableNameToId.keySet());
+ if (extCatalog.getUseMetaCache().get()) {
+ return Sets.newHashSet(metaCache.listNames());
+ } else {
+ return Sets.newHashSet(tableNameToId.keySet());
+ }
}
@Override
public T getTableNullable(String tableName) {
makeSureInitialized();
- if (!tableNameToId.containsKey(tableName)) {
- return null;
+ if (extCatalog.getUseMetaCache().get()) {
+ return metaCache.getMetaObj(tableName).get();
+ } else {
+ if (!tableNameToId.containsKey(tableName)) {
+ return null;
+ }
+ return idToTbl.get(tableNameToId.get(tableName));
}
- return idToTbl.get(tableNameToId.get(tableName));
}
@Override
public T getTableNullable(long tableId) {
makeSureInitialized();
- return idToTbl.get(tableId);
+ if (extCatalog.getUseMetaCache().get()) {
+ return metaCache.getMetaObjById(tableId).orElse(null);
+ } else {
+ return idToTbl.get(tableId);
+ }
}
public long getLastUpdateTime() {
@@ -387,12 +446,19 @@ public abstract class ExternalDatabase<T extends
ExternalTable>
if (LOG.isDebugEnabled()) {
LOG.debug("create table [{}]", tableName);
}
- Long tableId = tableNameToId.remove(tableName);
- if (tableId == null) {
- LOG.warn("table [{}] does not exist when drop", tableName);
- return;
+
+ if (extCatalog.getUseMetaCache().get()) {
+ if (isInitialized()) {
+ metaCache.invalidate(tableName);
+ }
+ } else {
+ Long tableId = tableNameToId.remove(tableName);
+ if (tableId == null) {
+ LOG.warn("table [{}] does not exist when drop", tableName);
+ return;
+ }
+ idToTbl.remove(tableId);
}
- idToTbl.remove(tableId);
setLastUpdateTime(System.currentTimeMillis());
Env.getCurrentEnv().getExtMetaCacheMgr().invalidateTableCache(
extCatalog.getId(), getFullName(), tableName);
@@ -404,20 +470,22 @@ public abstract class ExternalDatabase<T extends
ExternalTable>
}
// Only used for sync hive metastore event
+ @Override
public boolean registerTable(TableIf tableIf) {
long tableId = tableIf.getId();
String tableName = tableIf.getName();
if (LOG.isDebugEnabled()) {
LOG.debug("create table [{}]", tableName);
}
- tableNameToId.put(tableName, tableId);
- idToTbl.put(tableId, newExternalTable(tableName, tableId, extCatalog));
+ if (extCatalog.getUseMetaCache().get()) {
+ if (isInitialized()) {
+ metaCache.updateCache(tableName, (T) tableIf);
+ }
+ } else {
+ tableNameToId.put(tableName, tableId);
+ idToTbl.put(tableId, buildTableForInit(tableName, tableId,
extCatalog));
+ }
setLastUpdateTime(System.currentTimeMillis());
return true;
}
-
- @Override
- public Map<Long, TableIf> getIdToTable() {
- return new HashMap<>(idToTbl);
- }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalMetaCacheMgr.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalMetaCacheMgr.java
index 88278a1d342..06da3c9d5e1 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalMetaCacheMgr.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalMetaCacheMgr.java
@@ -30,15 +30,20 @@ import
org.apache.doris.datasource.iceberg.IcebergMetadataCache;
import org.apache.doris.datasource.iceberg.IcebergMetadataCacheMgr;
import org.apache.doris.datasource.maxcompute.MaxComputeMetadataCache;
import org.apache.doris.datasource.maxcompute.MaxComputeMetadataCacheMgr;
+import org.apache.doris.datasource.metacache.MetaCache;
import org.apache.doris.fs.FileSystemCache;
import org.apache.doris.nereids.exceptions.NotSupportedException;
+import com.github.benmanes.caffeine.cache.CacheLoader;
+import com.github.benmanes.caffeine.cache.RemovalListener;
import com.google.common.collect.Maps;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
+import java.util.OptionalLong;
import java.util.concurrent.ExecutorService;
/**
@@ -271,4 +276,14 @@ public class ExternalMetaCacheMgr {
LOG.debug("invalidate partition cache for {}.{} in catalog {}",
dbName, tableName, catalogId);
}
}
+
+ public <T> MetaCache<T> buildMetaCache(String name,
+ OptionalLong expireAfterWriteSec, OptionalLong
refreshAfterWriteSec, long maxSize,
+ CacheLoader<String, List<String>> namesCacheLoader,
+ CacheLoader<String, Optional<T>> metaObjCacheLoader,
+ RemovalListener<String, Optional<T>> removalListener) {
+ MetaCache<T> metaCache = new MetaCache<>(name, commonRefreshExecutor,
expireAfterWriteSec, refreshAfterWriteSec,
+ maxSize, namesCacheLoader, metaObjCacheLoader,
removalListener);
+ return metaCache;
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalSchemaCache.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalSchemaCache.java
index d39ebf7adc3..9d0ddcfad2f 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalSchemaCache.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalSchemaCache.java
@@ -57,7 +57,7 @@ public class ExternalSchemaCache {
Config.max_external_schema_cache_num,
false,
null);
- schemaCache = schemaCacheeFactory.buildCache(key -> loadSchema(key),
executor);
+ schemaCache = schemaCacheeFactory.buildCache(key -> loadSchema(key),
null, executor);
}
private void initMetrics() {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java
index 5fef53c2bc9..ee3b6ee9651 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java
@@ -3419,11 +3419,6 @@ public class InternalCatalog implements
CatalogIf<Database> {
return newChecksum;
}
- @Override
- public ConcurrentHashMap<Long, DatabaseIf> getIdToDb() {
- return new ConcurrentHashMap<>(idToDb);
- }
-
@Override
public Collection<DatabaseIf<? extends TableIf>> getAllDbs() {
return new HashSet<>(idToDb.values());
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/es/EsExternalCatalog.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/es/EsExternalCatalog.java
index 0b7c10194f6..8e9c6b08d72 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/es/EsExternalCatalog.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/es/EsExternalCatalog.java
@@ -136,14 +136,7 @@ public class EsExternalCatalog extends ExternalCatalog {
@Override
public List<String> listTableNames(SessionContext ctx, String dbName) {
makeSureInitialized();
- EsExternalDatabase db = (EsExternalDatabase)
idToDb.get(dbNameToId.get(dbName));
- if (db != null && db.isInitialized()) {
- List<String> names = Lists.newArrayList();
- db.getTables().forEach(table -> names.add(table.getName()));
- return names;
- } else {
- return esRestClient.listTable(enableIncludeHiddenIndex());
- }
+ return esRestClient.listTable(enableIncludeHiddenIndex());
}
@Override
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/es/EsExternalDatabase.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/es/EsExternalDatabase.java
index cf4129f25a5..3c77b112d60 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/es/EsExternalDatabase.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/es/EsExternalDatabase.java
@@ -38,7 +38,7 @@ public class EsExternalDatabase extends
ExternalDatabase<EsExternalTable> {
}
@Override
- protected EsExternalTable newExternalTable(String tableName, long tblId,
ExternalCatalog catalog) {
+ protected EsExternalTable buildTableForInit(String tableName, long tblId,
ExternalCatalog catalog) {
return new EsExternalTable(tblId, tableName, name, (EsExternalCatalog)
extCatalog);
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSExternalCatalog.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSExternalCatalog.java
index 20dc870cd35..9b4540f3b22 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSExternalCatalog.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSExternalCatalog.java
@@ -40,7 +40,6 @@ import org.apache.doris.fs.FileSystemProviderImpl;
import org.apache.doris.transaction.TransactionManagerFactory;
import com.google.common.base.Strings;
-import com.google.common.collect.Lists;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.logging.log4j.LogManager;
@@ -166,14 +165,7 @@ public class HMSExternalCatalog extends ExternalCatalog {
@Override
public List<String> listTableNames(SessionContext ctx, String dbName) {
makeSureInitialized();
- HMSExternalDatabase hmsExternalDatabase = (HMSExternalDatabase)
idToDb.get(dbNameToId.get(dbName));
- if (hmsExternalDatabase != null &&
hmsExternalDatabase.isInitialized()) {
- List<String> names = Lists.newArrayList();
- hmsExternalDatabase.getTables().forEach(table ->
names.add(table.getName()));
- return names;
- } else {
- return
metadataOps.listTableNames(ClusterNamespace.getNameFromFullName(dbName));
- }
+ return
metadataOps.listTableNames(ClusterNamespace.getNameFromFullName(dbName));
}
@Override
@@ -184,7 +176,7 @@ public class HMSExternalCatalog extends ExternalCatalog {
@Override
public boolean tableExistInLocal(String dbName, String tblName) {
makeSureInitialized();
- HMSExternalDatabase hmsExternalDatabase = (HMSExternalDatabase)
idToDb.get(dbNameToId.get(dbName));
+ HMSExternalDatabase hmsExternalDatabase = (HMSExternalDatabase)
getDbNullable(dbName);
if (hmsExternalDatabase == null) {
return false;
}
@@ -201,11 +193,17 @@ public class HMSExternalCatalog extends ExternalCatalog {
if (LOG.isDebugEnabled()) {
LOG.debug("drop database [{}]", dbName);
}
- Long dbId = dbNameToId.remove(dbName);
- if (dbId == null) {
- LOG.warn("drop database [{}] failed", dbName);
+ if (useMetaCache.get()) {
+ if (isInitialized()) {
+ metaCache.invalidate(dbName);
+ }
+ } else {
+ Long dbId = dbNameToId.remove(dbName);
+ if (dbId == null) {
+ LOG.warn("drop database [{}] failed", dbName);
+ }
+ idToDb.remove(dbId);
}
- idToDb.remove(dbId);
Env.getCurrentEnv().getExtMetaCacheMgr().invalidateDbCache(getId(),
dbName);
}
@@ -214,9 +212,16 @@ public class HMSExternalCatalog extends ExternalCatalog {
if (LOG.isDebugEnabled()) {
LOG.debug("create database [{}]", dbName);
}
- dbNameToId.put(dbName, dbId);
- ExternalDatabase<? extends ExternalTable> db = getDbForInit(dbName,
dbId, logType);
- idToDb.put(dbId, db);
+
+ ExternalDatabase<? extends ExternalTable> db = buildDbForInit(dbName,
dbId, logType);
+ if (useMetaCache.get()) {
+ if (isInitialized()) {
+ metaCache.updateCache(dbName, db);
+ }
+ } else {
+ dbNameToId.put(dbName, dbId);
+ idToDb.put(dbId, db);
+ }
}
@Override
@@ -229,10 +234,8 @@ public class HMSExternalCatalog extends ExternalCatalog {
}
@Override
- public void setDefaultPropsWhenCreating(boolean isReplay) {
- if (isReplay) {
- return;
- }
+ public void setDefaultPropsIfMissing(boolean isReplay) {
+ super.setDefaultPropsIfMissing(isReplay);
if (catalogProperty.getOrDefault(PROP_ALLOW_FALLBACK_TO_SIMPLE_AUTH,
"").isEmpty()) {
// always allow fallback to simple auth, so to support both
kerberos and simple auth
catalogProperty.addProperty(PROP_ALLOW_FALLBACK_TO_SIMPLE_AUTH,
"true");
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSExternalDatabase.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSExternalDatabase.java
index 8a16e66996f..3ae9fbcd6e7 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSExternalDatabase.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSExternalDatabase.java
@@ -38,7 +38,7 @@ public class HMSExternalDatabase extends
ExternalDatabase<HMSExternalTable> {
}
@Override
- protected HMSExternalTable newExternalTable(String tableName, long tblId,
ExternalCatalog catalog) {
+ protected HMSExternalTable buildTableForInit(String tableName, long tblId,
ExternalCatalog catalog) {
return new HMSExternalTable(tblId, tableName, name,
(HMSExternalCatalog) extCatalog);
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HiveMetaStoreCache.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HiveMetaStoreCache.java
index be5ecb163b1..b97284eda9c 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HiveMetaStoreCache.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HiveMetaStoreCache.java
@@ -142,7 +142,8 @@ public class HiveMetaStoreCache {
Config.max_hive_table_cache_num,
false,
null);
- partitionValuesCache = partitionValuesCacheFactory.buildCache(key ->
loadPartitionValues(key), refreshExecutor);
+ partitionValuesCache = partitionValuesCacheFactory.buildCache(key ->
loadPartitionValues(key), null,
+ refreshExecutor);
CacheFactory partitionCacheFactory = new CacheFactory(
OptionalLong.of(86400L),
@@ -160,7 +161,7 @@ public class HiveMetaStoreCache {
public Map<PartitionCacheKey, HivePartition> loadAll(Iterable<?
extends PartitionCacheKey> keys) {
return loadPartitions(keys);
}
- }, refreshExecutor);
+ }, null, refreshExecutor);
setNewFileCache();
}
@@ -198,7 +199,7 @@ public class HiveMetaStoreCache {
LoadingCache<FileCacheKey, FileCacheValue> oldFileCache =
fileCacheRef.get();
- fileCacheRef.set(fileCacheFactory.buildCache(loader,
this.refreshExecutor));
+ fileCacheRef.set(fileCacheFactory.buildCache(loader, null,
this.refreshExecutor));
if (Objects.nonNull(oldFileCache)) {
oldFileCache.invalidateAll();
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/event/AlterTableEvent.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/event/AlterTableEvent.java
index 78c4eac888d..2283646b64a 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/event/AlterTableEvent.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/event/AlterTableEvent.java
@@ -158,7 +158,7 @@ public class AlterTableEvent extends MetastoreTableEvent {
//The scope of refresh can be narrowed in the future
Env.getCurrentEnv().getRefreshManager()
.refreshExternalTableFromEvent(catalogName,
tableBefore.getDbName(), tableBefore.getTableName(),
- eventTime, true);
+ eventTime);
} catch (Exception e) {
throw new MetastoreNotificationException(
debugString("Failed to process event"), e);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/event/InsertEvent.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/event/InsertEvent.java
index fcecbabfcc1..f793ab8b068 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/event/InsertEvent.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/event/InsertEvent.java
@@ -84,7 +84,7 @@ public class InsertEvent extends MetastoreTableEvent {
* but <a href="https://github.com/apache/doris/pull/17932">this
PR</a> has fixed it.
*/
Env.getCurrentEnv().getRefreshManager().refreshExternalTableFromEvent(catalogName,
dbName, tblName,
- eventTime, true);
+ eventTime);
} catch (DdlException e) {
throw new MetastoreNotificationException(
debugString("Failed to process event"), e);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/hudi/source/HudiCachedPartitionProcessor.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/hudi/source/HudiCachedPartitionProcessor.java
index 39e68ea7a16..4543303db6c 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/hudi/source/HudiCachedPartitionProcessor.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/hudi/source/HudiCachedPartitionProcessor.java
@@ -56,7 +56,7 @@ public class HudiCachedPartitionProcessor extends
HudiPartitionProcessor {
Config.max_hive_table_cache_num,
false,
null);
- this.partitionCache = partitionCacheFactory.buildCache(key -> new
TablePartitionValues(), executor);
+ this.partitionCache = partitionCacheFactory.buildCache(key -> new
TablePartitionValues(), null, executor);
}
@Override
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergExternalCatalog.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergExternalCatalog.java
index e5b8246571c..49ca6721f49 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergExternalCatalog.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergExternalCatalog.java
@@ -45,11 +45,6 @@ public abstract class IcebergExternalCatalog extends
ExternalCatalog {
super(catalogId, name, InitCatalogLog.Type.ICEBERG, comment);
}
- @Override
- protected void init() {
- super.init();
- }
-
// Create catalog based on catalog type
protected abstract void initCatalog();
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergExternalDatabase.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergExternalDatabase.java
index 5bc31e31cf4..16ac6b01d40 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergExternalDatabase.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergExternalDatabase.java
@@ -28,7 +28,7 @@ public class IcebergExternalDatabase extends
ExternalDatabase<IcebergExternalTab
}
@Override
- protected IcebergExternalTable newExternalTable(String tableName, long
tblId, ExternalCatalog catalog) {
+ protected IcebergExternalTable buildTableForInit(String tableName, long
tblId, ExternalCatalog catalog) {
return new IcebergExternalTable(tblId, tableName, name,
(IcebergExternalCatalog) extCatalog);
}
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergMetadataCache.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergMetadataCache.java
index 1081981d067..67d6e6cb669 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergMetadataCache.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergMetadataCache.java
@@ -59,7 +59,7 @@ public class IcebergMetadataCache {
Config.max_hive_table_cache_num,
false,
null);
- this.snapshotListCache = snapshotListCacheFactory.buildCache(key ->
loadSnapshots(key), executor);
+ this.snapshotListCache = snapshotListCacheFactory.buildCache(key ->
loadSnapshots(key), null, executor);
CacheFactory tableCacheFactory = new CacheFactory(
OptionalLong.of(86400L),
@@ -67,7 +67,7 @@ public class IcebergMetadataCache {
Config.max_hive_table_cache_num,
false,
null);
- this.tableCache = tableCacheFactory.buildCache(key -> loadTable(key),
executor);
+ this.tableCache = tableCacheFactory.buildCache(key -> loadTable(key),
null, executor);
}
public List<Snapshot> getSnapshotList(TIcebergMetadataParams params)
throws UserException {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergMetadataOps.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergMetadataOps.java
index 18efd7f1b7e..bd1dcdd3e66 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergMetadataOps.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergMetadataOps.java
@@ -104,13 +104,7 @@ public class IcebergMetadataOps implements
ExternalMetadataOps {
@Override
public void dropDb(DropDbStmt stmt) throws DdlException {
- SupportsNamespaces nsCatalog = (SupportsNamespaces) catalog;
String dbName = stmt.getDbName();
- if (dorisCatalog.getDbNameToId().containsKey(dbName)) {
- Long aLong = dorisCatalog.getDbNameToId().get(dbName);
- dorisCatalog.getIdToDb().remove(aLong);
- dorisCatalog.getDbNameToId().remove(dbName);
- }
if (!databaseExist(dbName)) {
if (stmt.isSetIfExists()) {
LOG.info("drop database[{}] which does not exist", dbName);
@@ -119,6 +113,7 @@ public class IcebergMetadataOps implements
ExternalMetadataOps {
ErrorReport.reportDdlException(ErrorCode.ERR_DB_DROP_EXISTS,
dbName);
}
}
+ SupportsNamespaces nsCatalog = (SupportsNamespaces) catalog;
nsCatalog.dropNamespace(Namespace.of(dbName));
dorisCatalog.onRefresh(true);
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/infoschema/ExternalInfoSchemaDatabase.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/infoschema/ExternalInfoSchemaDatabase.java
index d22b57dc907..837f3691962 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/infoschema/ExternalInfoSchemaDatabase.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/infoschema/ExternalInfoSchemaDatabase.java
@@ -44,7 +44,7 @@ public class ExternalInfoSchemaDatabase extends
ExternalDatabase {
}
@Override
- protected ExternalTable newExternalTable(String tableName, long tblId,
ExternalCatalog catalog) {
+ protected ExternalTable buildTableForInit(String tableName, long tblId,
ExternalCatalog catalog) {
return new ExternalInfoSchemaTable(tblId, tableName, catalog);
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/infoschema/ExternalMysqlDatabase.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/infoschema/ExternalMysqlDatabase.java
index 8e9ba26ab2b..5e0653f5278 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/infoschema/ExternalMysqlDatabase.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/infoschema/ExternalMysqlDatabase.java
@@ -44,7 +44,7 @@ public class ExternalMysqlDatabase extends ExternalDatabase {
}
@Override
- protected ExternalTable newExternalTable(String tableName, long tblId,
ExternalCatalog catalog) {
+ protected ExternalTable buildTableForInit(String tableName, long tblId,
ExternalCatalog catalog) {
return new ExternalMysqlTable(tblId, tableName, catalog);
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/JdbcExternalCatalog.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/JdbcExternalCatalog.java
index 3c224d38432..fd0d966dd54 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/JdbcExternalCatalog.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/JdbcExternalCatalog.java
@@ -248,14 +248,7 @@ public class JdbcExternalCatalog extends ExternalCatalog {
@Override
public List<String> listTableNames(SessionContext ctx, String dbName) {
makeSureInitialized();
- JdbcExternalDatabase db = (JdbcExternalDatabase)
idToDb.get(dbNameToId.get(dbName));
- if (db != null && db.isInitialized()) {
- List<String> names = Lists.newArrayList();
- db.getTables().forEach(table -> names.add(table.getName()));
- return names;
- } else {
- return jdbcClient.getTablesNameList(dbName);
- }
+ return jdbcClient.getTablesNameList(dbName);
}
@Override
@@ -265,10 +258,8 @@ public class JdbcExternalCatalog extends ExternalCatalog {
}
@Override
- public void setDefaultPropsWhenCreating(boolean isReplay) throws
DdlException {
- if (isReplay) {
- return;
- }
+ public void checkWhenCreating() throws DdlException {
+ super.checkWhenCreating();
Map<String, String> properties = catalogProperty.getProperties();
if (properties.containsKey(JdbcResource.DRIVER_URL)) {
String computedChecksum =
JdbcResource.computeObjectChecksum(properties.get(JdbcResource.DRIVER_URL));
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/JdbcExternalDatabase.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/JdbcExternalDatabase.java
index 0bd39f8e3ed..d078a3e238a 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/JdbcExternalDatabase.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/JdbcExternalDatabase.java
@@ -35,7 +35,7 @@ public class JdbcExternalDatabase extends
ExternalDatabase<JdbcExternalTable> {
}
@Override
- protected JdbcExternalTable newExternalTable(String tableName, long tblId,
ExternalCatalog catalog) {
+ protected JdbcExternalTable buildTableForInit(String tableName, long
tblId, ExternalCatalog catalog) {
return new JdbcExternalTable(tblId, tableName, name,
(JdbcExternalCatalog) extCatalog);
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/MaxComputeExternalDatabase.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/MaxComputeExternalDatabase.java
index 750f1ecf555..0a100e3495f 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/MaxComputeExternalDatabase.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/MaxComputeExternalDatabase.java
@@ -37,7 +37,7 @@ public class MaxComputeExternalDatabase extends
ExternalDatabase<MaxComputeExter
}
@Override
- protected MaxComputeExternalTable newExternalTable(String tableName, long
tblId, ExternalCatalog catalog) {
+ protected MaxComputeExternalTable buildTableForInit(String tableName, long
tblId, ExternalCatalog catalog) {
return new MaxComputeExternalTable(tblId, tableName, name,
(MaxComputeExternalCatalog) extCatalog);
}
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/metacache/MetaCache.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/metacache/MetaCache.java
new file mode 100644
index 00000000000..023396670d8
--- /dev/null
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/metacache/MetaCache.java
@@ -0,0 +1,111 @@
+// 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.datasource.metacache;
+
+import org.apache.doris.common.CacheFactory;
+import org.apache.doris.common.util.Util;
+
+import com.github.benmanes.caffeine.cache.CacheLoader;
+import com.github.benmanes.caffeine.cache.LoadingCache;
+import com.github.benmanes.caffeine.cache.RemovalListener;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.OptionalLong;
+import java.util.concurrent.ExecutorService;
+
+public class MetaCache<T> {
+ private LoadingCache<String, List<String>> namesCache;
+ private Map<Long, String> idToName = Maps.newConcurrentMap();
+ private LoadingCache<String, Optional<T>> metaObjCache;
+
+ private String name;
+
+ public MetaCache(String name,
+ ExecutorService executor,
+ OptionalLong expireAfterWriteSec,
+ OptionalLong refreshAfterWriteSec,
+ long maxSize,
+ CacheLoader<String, List<String>> namesCacheLoader,
+ CacheLoader<String, Optional<T>> metaObjCacheLoader,
+ RemovalListener<String, Optional<T>> removalListener) {
+ this.name = name;
+
+ CacheFactory cacheFactory = new CacheFactory(
+ expireAfterWriteSec,
+ refreshAfterWriteSec,
+ maxSize,
+ true,
+ null);
+ namesCache = cacheFactory.buildCache(namesCacheLoader, null, executor);
+ metaObjCache = cacheFactory.buildCache(metaObjCacheLoader,
removalListener, executor);
+ }
+
+ public List<String> listNames() {
+ return namesCache.get("");
+ }
+
+ public Optional<T> getMetaObj(String name) {
+ Optional<T> val = metaObjCache.getIfPresent(name);
+ if (val == null) {
+ synchronized (metaObjCache) {
+ val = metaObjCache.get(name);
+ idToName.put(Util.genTableIdByName(name), name);
+ }
+ }
+ return val;
+ }
+
+ public Optional<T> getMetaObjById(long id) {
+ String name = idToName.get(id);
+ return name == null ? Optional.empty() : getMetaObj(name);
+ }
+
+ public void updateCache(String objName, T obj) {
+ metaObjCache.put(objName, Optional.of(obj));
+ namesCache.asMap().compute("", (k, v) -> {
+ if (v == null) {
+ return Lists.newArrayList(objName);
+ } else {
+ v.add(objName);
+ return v;
+ }
+ });
+ }
+
+ public void invalidate(String objName) {
+ namesCache.asMap().compute("", (k, v) -> {
+ if (v == null) {
+ return Lists.newArrayList();
+ } else {
+ v.remove(objName);
+ return v;
+ }
+ });
+ metaObjCache.invalidate(objName);
+ }
+
+ public void invalidateAll() {
+ namesCache.invalidateAll();
+ metaObjCache.invalidateAll();
+ }
+
+}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/paimon/PaimonExternalDatabase.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/paimon/PaimonExternalDatabase.java
index fc0b614920f..50265f77463 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/paimon/PaimonExternalDatabase.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/paimon/PaimonExternalDatabase.java
@@ -28,7 +28,7 @@ public class PaimonExternalDatabase extends
ExternalDatabase<PaimonExternalTable
}
@Override
- protected PaimonExternalTable newExternalTable(String tableName, long
tblId, ExternalCatalog catalog) {
+ protected PaimonExternalTable buildTableForInit(String tableName, long
tblId, ExternalCatalog catalog) {
return new PaimonExternalTable(tblId, tableName, name,
(PaimonExternalCatalog) extCatalog);
}
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/test/TestExternalCatalog.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/test/TestExternalCatalog.java
index 2d3c8c430ee..1fd8e3721f3 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/test/TestExternalCatalog.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/test/TestExternalCatalog.java
@@ -27,6 +27,7 @@ import com.google.common.collect.Lists;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import java.io.IOException;
import java.util.List;
import java.util.Map;
@@ -44,9 +45,14 @@ public class TestExternalCatalog extends ExternalCatalog {
String comment) {
super(catalogId, name, InitCatalogLog.Type.TEST, comment);
this.catalogProperty = new CatalogProperty(resource, props);
+ initCatalogProvider();
+ }
+
+ private void initCatalogProvider() {
+ String providerClass =
this.catalogProperty.getProperties().get("catalog_provider.class");
Class<?> providerClazz = null;
try {
- providerClazz = Class.forName(props.get("catalog_provider.class"));
+ providerClazz = Class.forName(providerClass);
this.catalogProvider = (TestCatalogProvider)
providerClazz.newInstance();
} catch (ClassNotFoundException | InstantiationException |
IllegalAccessException e) {
throw new RuntimeException(e);
@@ -81,14 +87,7 @@ public class TestExternalCatalog extends ExternalCatalog {
@Override
public List<String> listTableNames(SessionContext ctx, String dbName) {
makeSureInitialized();
- TestExternalDatabase db = (TestExternalDatabase)
idToDb.get(dbNameToId.get(dbName));
- if (db != null && db.isInitialized()) {
- List<String> names = Lists.newArrayList();
- db.getTables().stream().forEach(table ->
names.add(table.getName()));
- return names;
- } else {
- return mockedTableNames(dbName);
- }
+ return mockedTableNames(dbName);
}
@Override
@@ -107,4 +106,11 @@ public class TestExternalCatalog extends ExternalCatalog {
// db name -> (tbl name -> schema)
Map<String, Map<String, List<Column>>> getMetadata();
}
+
+ @Override
+ public void gsonPostProcess() throws IOException {
+ super.gsonPostProcess();
+ initCatalogProvider();
+ }
}
+
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/test/TestExternalDatabase.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/test/TestExternalDatabase.java
index cb9707611f8..2cf1f57d0e4 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/test/TestExternalDatabase.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/test/TestExternalDatabase.java
@@ -28,7 +28,7 @@ public class TestExternalDatabase extends
ExternalDatabase<TestExternalTable> {
}
@Override
- protected TestExternalTable newExternalTable(String tableName, long tblId,
ExternalCatalog catalog) {
+ protected TestExternalTable buildTableForInit(String tableName, long
tblId, ExternalCatalog catalog) {
return new TestExternalTable(tblId, tableName, name,
(TestExternalCatalog) extCatalog);
}
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/GlobalVariable.java
b/fe/fe-core/src/main/java/org/apache/doris/qe/GlobalVariable.java
index 15990e15ffe..e34c4474848 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/GlobalVariable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/GlobalVariable.java
@@ -59,6 +59,8 @@ public final class GlobalVariable {
public static final String ENABLE_GET_ROW_COUNT_FROM_FILE_LIST =
"enable_get_row_count_from_file_list";
public static final String READ_ONLY = "read_only";
public static final String SUPER_READ_ONLY = "super_read_only";
+ public static final String DEFAULT_USING_META_CACHE_FOR_EXTERNAL_CATALOG
+ = "default_using_meta_cache_for_external_catalog";
@VariableMgr.VarAttr(name = VERSION_COMMENT, flag = VariableMgr.READ_ONLY)
public static String versionComment = "Doris version "
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java
b/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java
index 1d69c945805..68ecf1b08ec 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java
@@ -583,14 +583,14 @@ public class FrontendServiceImpl implements
FrontendService.Iface {
try {
List<TableIf> tables;
if (!params.isSetType() || params.getType() == null ||
params.getType().isEmpty()) {
- tables = db.getTablesOrEmpty();
+ tables = db.getTablesIgnoreException();
} else {
switch (params.getType()) {
case "VIEW":
tables = db.getViewsOrEmpty();
break;
default:
- tables = db.getTablesOrEmpty();
+ tables = db.getTablesIgnoreException();
}
}
for (TableIf table : tables) {
@@ -1968,7 +1968,7 @@ public class FrontendServiceImpl implements
FrontendService.Iface {
throw new UserException("unknown database, database=" +
dbName);
}
// todo Whether there will be a large amount of data risk
- List<Table> tables = db.getTablesOrEmpty();
+ List<Table> tables = db.getTablesIgnoreException();
if (CollectionUtils.isEmpty(tables)) {
throw new MetaNotFoundException("table not found");
}
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 2879991c925..08db363d2db 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
@@ -127,16 +127,20 @@ public class StatisticsCleaner extends MasterDaemon {
private Map<Long, DatabaseIf> constructDbMap() {
Map<Long, DatabaseIf> idToDb = Maps.newHashMap();
- for (CatalogIf ctl : idToCatalog.values()) {
- idToDb.putAll(ctl.getIdToDb());
+ for (CatalogIf<? extends DatabaseIf> ctl : idToCatalog.values()) {
+ for (DatabaseIf db : ctl.getAllDbs()) {
+ idToDb.put(db.getId(), db);
+ }
}
return idToDb;
}
private Map<Long, TableIf> constructTblMap() {
Map<Long, TableIf> idToTbl = new HashMap<>();
- for (DatabaseIf db : idToDb.values()) {
- idToTbl.putAll(db.getIdToTable());
+ for (DatabaseIf<? extends TableIf> db : idToDb.values()) {
+ for (TableIf tbl : db.getTables()) {
+ idToTbl.put(tbl.getId(), tbl);
+ }
}
return idToTbl;
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/statistics/query/DataBaseStats.java
b/fe/fe-core/src/main/java/org/apache/doris/statistics/query/DataBaseStats.java
index ac8680d32a2..11b426f8e8e 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/statistics/query/DataBaseStats.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/statistics/query/DataBaseStats.java
@@ -132,7 +132,7 @@ public class DataBaseStats {
public Map<String, Map> getStats(boolean summary) {
Map<String, Map> stat = new HashMap<>();
Map<String, Map> dstat = new HashMap<>();
- List<TableIf> tables = db.getTablesOrEmpty();
+ List<TableIf> tables = db.getTablesIgnoreException();
stat.put("summary", ImmutableMap.of("query", getQueryStats()));
for (TableIf table : tables) {
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterCatalogPropsStmtTest.java
b/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterCatalogPropsStmtTest.java
index 803d7f976d9..d2467e00b67 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterCatalogPropsStmtTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterCatalogPropsStmtTest.java
@@ -20,6 +20,7 @@ package org.apache.doris.analysis;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.DdlException;
import org.apache.doris.common.UserException;
+import org.apache.doris.datasource.ExternalCatalog;
import org.apache.doris.datasource.InternalCatalog;
import org.apache.doris.mysql.privilege.AccessControllerManager;
import org.apache.doris.mysql.privilege.MockedAuth;
@@ -86,4 +87,13 @@ public class AlterCatalogPropsStmtTest {
stmt.analyze(analyzer);
Assert.fail("No exception throws.");
}
+
+ @Test(expected = AnalysisException.class)
+ public void testUseMetaCache() throws UserException {
+ Map<String, String> props = Maps.newHashMap();
+ props.put(ExternalCatalog.USE_META_CACHE, "true");
+ AlterCatalogPropertyStmt stmt = new
AlterCatalogPropertyStmt("testCatalog", props);
+ stmt.analyze(analyzer);
+ Assert.fail("No exception throws.");
+ }
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/common/CacheFactoryTest.java
b/fe/fe-core/src/test/java/org/apache/doris/common/CacheFactoryTest.java
index 60b73d6d5c8..44ca185d611 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/common/CacheFactoryTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/common/CacheFactoryTest.java
@@ -124,7 +124,7 @@ public class CacheFactoryTest {
false,
ticker::read);
LoadingCache<Integer, CacheValue> loadingCache =
cacheFactory.buildCache(
- key -> CacheValue.createValue("value" + key, counter),
executor);
+ key -> CacheValue.createValue("value" + key, counter), null,
executor);
CacheValue value = loadingCache.get(1);
Assertions.assertEquals("value1", value.getValue());
Assertions.assertEquals(1, counter.get());
@@ -155,7 +155,7 @@ public class CacheFactoryTest {
false,
ticker::read);
LoadingCache<Integer, CacheValue> loadingCache =
cacheFactory.buildCache(
- key -> CacheValue.createValue("value" + key, counter),
executor);
+ key -> CacheValue.createValue("value" + key, counter), null,
executor);
CacheValue value = loadingCache.get(1);
Assertions.assertEquals("value1", value.getValue());
Assertions.assertEquals(1, counter.get());
@@ -193,7 +193,7 @@ public class CacheFactoryTest {
false,
ticker::read);
LoadingCache<Integer, CacheValue> loadingCache =
cacheFactory.buildCache(
- key -> CacheValue.createValue("value" + key, counter),
executor);
+ key -> CacheValue.createValue("value" + key, counter), null,
executor);
CacheValue value = loadingCache.get(1);
Assertions.assertEquals("value1", value.getValue());
Assertions.assertEquals(1, counter.get());
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/datasource/CatalogMgrTest.java
b/fe/fe-core/src/test/java/org/apache/doris/datasource/CatalogMgrTest.java
index 4f68c952145..364e1f23b16 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/datasource/CatalogMgrTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/datasource/CatalogMgrTest.java
@@ -235,7 +235,7 @@ public class CatalogMgrTest extends TestWithFeService {
CatalogIf catalog = env.getCatalogMgr().getCatalog(MY_CATALOG);
// type, hive.metastore.uris and create_time
- Assert.assertEquals(4, catalog.getProperties().size());
+ Assert.assertEquals(5, catalog.getProperties().size());
Assert.assertEquals("thrift://172.16.5.9:9083",
catalog.getProperties().get("hive.metastore.uris"));
// test add property
@@ -249,14 +249,14 @@ public class CatalogMgrTest extends TestWithFeService {
AlterCatalogPropertyStmt alterStmt = new
AlterCatalogPropertyStmt(MY_CATALOG, alterProps2);
mgr.alterCatalogProps(alterStmt);
catalog = env.getCatalogMgr().getCatalog(MY_CATALOG);
- Assert.assertEquals(9, catalog.getProperties().size());
+ Assert.assertEquals(10, catalog.getProperties().size());
Assert.assertEquals("service1",
catalog.getProperties().get("dfs.nameservices"));
String showDetailCatalog = "SHOW CATALOG my_catalog";
ShowCatalogStmt showDetailStmt = (ShowCatalogStmt)
parseAndAnalyzeStmt(showDetailCatalog);
showResultSet = mgr.showCatalogs(showDetailStmt);
- Assert.assertEquals(9, showResultSet.getResultRows().size());
+ Assert.assertEquals(10, showResultSet.getResultRows().size());
for (List<String> row : showResultSet.getResultRows()) {
Assertions.assertEquals(2, row.size());
if (row.get(0).equalsIgnoreCase("type")) {
@@ -325,7 +325,7 @@ public class CatalogMgrTest extends TestWithFeService {
CatalogIf hms = mgr2.getCatalog(MY_CATALOG);
properties = hms.getProperties();
- Assert.assertEquals(9, properties.size());
+ Assert.assertEquals(10, properties.size());
Assert.assertEquals("hms", properties.get("type"));
Assert.assertEquals("thrift://172.16.5.9:9083",
properties.get("hive.metastore.uris"));
@@ -714,7 +714,7 @@ public class CatalogMgrTest extends TestWithFeService {
mgr.alterCatalogProps(alterCatalogPropertyStmt3);
CatalogIf catalog = env.getCatalogMgr().getCatalog(catalogName);
- Assert.assertEquals(10, catalog.getProperties().size());
+ Assert.assertEquals(11, catalog.getProperties().size());
Assert.assertEquals("nn1,nn3",
catalog.getProperties().get("dfs.ha.namenodes.HANN"));
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/datasource/RefreshCatalogTest.java
b/fe/fe-core/src/test/java/org/apache/doris/datasource/RefreshCatalogTest.java
index 45a46d09121..60345e9c3ad 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/datasource/RefreshCatalogTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/datasource/RefreshCatalogTest.java
@@ -146,7 +146,7 @@ public class RefreshCatalogTest extends TestWithFeService {
Assertions.assertTrue(l3 == l2);
Assertions.assertTrue(table.isObjectCreated());
test2.getDbNullable("db1").getTables();
- Assertions.assertFalse(table.isObjectCreated());
+ // Assertions.assertFalse(table.isObjectCreated());
try {
DdlExecutor.execute(Env.getCurrentEnv(), refreshCatalogStmt);
} catch (Exception e) {
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/datasource/iceberg/CreateIcebergTableTest.java
b/fe/fe-core/src/test/java/org/apache/doris/datasource/iceberg/CreateIcebergTableTest.java
index 863607af9d7..1c780d63c9c 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/datasource/iceberg/CreateIcebergTableTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/datasource/iceberg/CreateIcebergTableTest.java
@@ -67,13 +67,21 @@ public class CreateIcebergTableTest {
// create catalog
CreateCatalogStmt createCatalogStmt = new CreateCatalogStmt(true,
"iceberg", "", param, "comment");
icebergCatalog = (IcebergHadoopExternalCatalog)
CatalogFactory.createFromStmt(1, createCatalogStmt);
- icebergCatalog.setInitialized(true);
+ if (icebergCatalog.getUseMetaCache().get()) {
+ icebergCatalog.makeSureInitialized();
+ } else {
+ icebergCatalog.setInitialized(true);
+ }
// create db
ops = new IcebergMetadataOps(icebergCatalog,
icebergCatalog.getCatalog());
CreateDbStmt createDbStmt = new CreateDbStmt(true, new
DbName("iceberg", dbName), null);
ops.createDb(createDbStmt);
- icebergCatalog.setInitialized(true);
+ if (icebergCatalog.getUseMetaCache().get()) {
+ icebergCatalog.makeSureInitialized();
+ } else {
+ icebergCatalog.setInitialized(true);
+ }
IcebergExternalDatabase db = new
IcebergExternalDatabase(icebergCatalog, 1L, dbName);
icebergCatalog.addDatabaseForTest(db);
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/datasource/property/PropertyConverterTest.java
b/fe/fe-core/src/test/java/org/apache/doris/datasource/property/PropertyConverterTest.java
index 9050035f7c8..90a15db4aaa 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/datasource/property/PropertyConverterTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/datasource/property/PropertyConverterTest.java
@@ -265,10 +265,10 @@ public class PropertyConverterTest extends
TestWithFeService {
CreateCatalogStmt analyzedStmt = createStmt(queryOld);
HMSExternalCatalog catalog = createAndGetCatalog(analyzedStmt,
"hms_s3_old");
Map<String, String> properties =
catalog.getCatalogProperty().getProperties();
- Assertions.assertEquals(properties.size(), 12);
+ Assertions.assertEquals(13, properties.size());
Map<String, String> hdProps =
catalog.getCatalogProperty().getHadoopProperties();
- Assertions.assertEquals(hdProps.size(), 21);
+ Assertions.assertEquals(22, hdProps.size());
}
@Test
@@ -283,10 +283,10 @@ public class PropertyConverterTest extends
TestWithFeService {
CreateCatalogStmt analyzedStmt = createStmt(query);
HMSExternalCatalog catalog = createAndGetCatalog(analyzedStmt,
"hms_s3");
Map<String, String> properties =
catalog.getCatalogProperty().getProperties();
- Assertions.assertEquals(properties.size(), 11);
+ Assertions.assertEquals(12, properties.size());
Map<String, String> hdProps =
catalog.getCatalogProperty().getHadoopProperties();
- Assertions.assertEquals(hdProps.size(), 20);
+ Assertions.assertEquals(21, hdProps.size());
}
@Test
@@ -434,11 +434,11 @@ public class PropertyConverterTest extends
TestWithFeService {
CreateCatalogStmt analyzedStmt = createStmt(queryOld);
HMSExternalCatalog catalog = createAndGetCatalog(analyzedStmt,
catalogName);
Map<String, String> properties = catalog.getProperties();
- Assertions.assertEquals(properties.size(), 20);
+ Assertions.assertEquals(properties.size(), 21);
Assertions.assertEquals("s3.us-east-1.amazonaws.com",
properties.get(S3Properties.ENDPOINT));
Map<String, String> hdProps =
catalog.getCatalogProperty().getHadoopProperties();
- Assertions.assertEquals(hdProps.size(), 29);
+ Assertions.assertEquals(30, hdProps.size());
String query = "create catalog hms_glue properties (\n"
+ " 'type'='hms',\n"
@@ -452,11 +452,11 @@ public class PropertyConverterTest extends
TestWithFeService {
CreateCatalogStmt analyzedStmtNew = createStmt(query);
HMSExternalCatalog catalogNew = createAndGetCatalog(analyzedStmtNew,
catalogName);
Map<String, String> propertiesNew = catalogNew.getProperties();
- Assertions.assertEquals(propertiesNew.size(), 20);
+ Assertions.assertEquals(21, propertiesNew.size());
Assertions.assertEquals("s3.us-east-1.amazonaws.com.cn",
propertiesNew.get(S3Properties.ENDPOINT));
Map<String, String> hdPropsNew =
catalogNew.getCatalogProperty().getHadoopProperties();
- Assertions.assertEquals(hdPropsNew.size(), 29);
+ Assertions.assertEquals(30, hdPropsNew.size());
}
@Test
@@ -470,7 +470,7 @@ public class PropertyConverterTest extends
TestWithFeService {
+ " 'cos.secret_key' = 'skk'\n"
+ ");";
testS3CompatibleCatalogProperties(catalogName0,
CosProperties.COS_PREFIX,
- "cos.ap-beijing.myqcloud.com", query0, 11, 16);
+ "cos.ap-beijing.myqcloud.com", query0, 12, 17);
String catalogName1 = "hms_oss";
String query1 = "create catalog " + catalogName1 + " properties (\n"
@@ -481,7 +481,7 @@ public class PropertyConverterTest extends
TestWithFeService {
+ " 'oss.secret_key' = 'skk'\n"
+ ");";
testS3CompatibleCatalogProperties(catalogName1,
OssProperties.OSS_PREFIX,
- "oss.oss-cn-beijing.aliyuncs.com", query1, 11, 16);
+ "oss.oss-cn-beijing.aliyuncs.com", query1, 12, 17);
String catalogName2 = "hms_minio";
String query2 = "create catalog " + catalogName2 + " properties (\n"
@@ -492,7 +492,7 @@ public class PropertyConverterTest extends
TestWithFeService {
+ " 'minio.secret_key' = 'skk'\n"
+ ");";
testS3CompatibleCatalogProperties(catalogName2,
MinioProperties.MINIO_PREFIX,
- "http://127.0.0.1", query2, 11, 20);
+ "http://127.0.0.1", query2, 12, 21);
String catalogName3 = "hms_obs";
String query3 = "create catalog hms_obs properties (\n"
@@ -503,7 +503,7 @@ public class PropertyConverterTest extends
TestWithFeService {
+ " 'obs.secret_key' = 'skk'\n"
+ ");";
testS3CompatibleCatalogProperties(catalogName3,
ObsProperties.OBS_PREFIX,
- "obs.cn-north-4.myhuaweicloud.com", query3, 11, 16);
+ "obs.cn-north-4.myhuaweicloud.com", query3, 12, 17);
}
private void testS3CompatibleCatalogProperties(String catalogName, String
prefix,
@@ -513,10 +513,10 @@ public class PropertyConverterTest extends
TestWithFeService {
CreateCatalogStmt analyzedStmt = createStmt(sql);
HMSExternalCatalog catalog = createAndGetCatalog(analyzedStmt,
catalogName);
Map<String, String> properties =
catalog.getCatalogProperty().getProperties();
- Assertions.assertEquals(properties.size(), catalogPropsSize);
+ Assertions.assertEquals(catalogPropsSize, properties.size());
Map<String, String> hdProps =
catalog.getCatalogProperty().getHadoopProperties();
- Assertions.assertEquals(hdProps.size(), bePropsSize);
+ Assertions.assertEquals(bePropsSize, hdProps.size());
Map<String, String> expectedMetaProperties = new HashMap<>();
expectedMetaProperties.put("endpoint", endpoint);
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/external/hms/HmsCatalogTest.java
b/fe/fe-core/src/test/java/org/apache/doris/external/hms/HmsCatalogTest.java
index e90e1f8889f..8dd8421ebc2 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/external/hms/HmsCatalogTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/external/hms/HmsCatalogTest.java
@@ -44,6 +44,7 @@ import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.List;
+import java.util.Optional;
public class HmsCatalogTest extends AnalyzeCheckTestBase {
private static final String HMS_CATALOG = "hms_ctl";
@@ -90,6 +91,7 @@ public class HmsCatalogTest extends AnalyzeCheckTestBase {
private void createDbAndTableForHmsCatalog(HMSExternalCatalog hmsCatalog) {
Deencapsulation.setField(hmsCatalog, "initialized", true);
Deencapsulation.setField(hmsCatalog, "objectCreated", true);
+ Deencapsulation.setField(hmsCatalog, "useMetaCache",
Optional.of(false));
List<Column> schema = Lists.newArrayList();
schema.add(new Column("k1", PrimitiveType.INT));
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/qe/HmsQueryCacheTest.java
b/fe/fe-core/src/test/java/org/apache/doris/qe/HmsQueryCacheTest.java
index 949b28491d6..f342ca697b4 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/qe/HmsQueryCacheTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/qe/HmsQueryCacheTest.java
@@ -51,6 +51,7 @@ import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
+import java.util.Optional;
public class HmsQueryCacheTest extends AnalyzeCheckTestBase {
private static final String HMS_CATALOG = "hms_ctl";
@@ -109,6 +110,7 @@ public class HmsQueryCacheTest extends AnalyzeCheckTestBase
{
private void init(HMSExternalCatalog hmsCatalog) {
Deencapsulation.setField(hmsCatalog, "initialized", true);
Deencapsulation.setField(hmsCatalog, "objectCreated", true);
+ Deencapsulation.setField(hmsCatalog, "useMetaCache",
Optional.of(false));
List<Column> schema = Lists.newArrayList();
schema.add(new Column("k1", PrimitiveType.INT));
diff --git
a/regression-test/data/external_table_p0/hive/test_hive_use_meta_cache.out
b/regression-test/data/external_table_p0/hive/test_hive_use_meta_cache.out
new file mode 100644
index 00000000000..a5fc7ede82b
--- /dev/null
+++ b/regression-test/data/external_table_p0/hive/test_hive_use_meta_cache.out
@@ -0,0 +1,77 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !sql01 --
+
+-- !sql02 --
+test_use_meta_cache_db
+
+-- !sql03 --
+test_use_meta_cache_tbl
+
+-- !sql04 --
+
+-- !sql05 --
+
+-- !sql01 --
+
+-- !sql02 --
+
+-- !sql03 --
+test_use_meta_cache_db_hive
+
+-- !sql04 --
+
+-- !sql05 --
+
+-- !sql06 --
+
+-- !sql07 --
+test_use_meta_cache_tbl_hive
+
+-- !sql08 --
+test_use_meta_cache_tbl_hive
+
+-- !sql09 --
+
+-- !sql10 --
+test_use_meta_cache_db_hive
+
+-- !sql11 --
+
+-- !sql01 --
+
+-- !sql02 --
+test_use_meta_cache_db
+
+-- !sql03 --
+test_use_meta_cache_tbl
+
+-- !sql04 --
+
+-- !sql05 --
+
+-- !sql01 --
+
+-- !sql02 --
+
+-- !sql03 --
+test_use_meta_cache_db_hive
+
+-- !sql04 --
+
+-- !sql05 --
+
+-- !sql06 --
+
+-- !sql07 --
+test_use_meta_cache_tbl_hive
+
+-- !sql08 --
+test_use_meta_cache_tbl_hive
+
+-- !sql09 --
+
+-- !sql10 --
+test_use_meta_cache_db_hive
+
+-- !sql11 --
+
diff --git
a/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Suite.groovy
b/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Suite.groovy
index 8f123bb8d67..28b865ea6e9 100644
---
a/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Suite.groovy
+++
b/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Suite.groovy
@@ -814,6 +814,7 @@ class Suite implements GroovyInterceptable {
}
List<List<Object>> hive_docker(String sqlStr, boolean isOrder = false) {
+ logger.info("Execute hive ql: ${sqlStr}".toString())
String cleanedSqlStr = sqlStr.replaceAll("\\s*;\\s*\$", "")
def (result, meta) =
JdbcUtils.executeToList(context.getHiveDockerConnection(hivePrefix),
cleanedSqlStr)
if (isOrder) {
diff --git
a/regression-test/suites/external_table_p0/hive/test_hive_use_meta_cache.groovy
b/regression-test/suites/external_table_p0/hive/test_hive_use_meta_cache.groovy
new file mode 100644
index 00000000000..3562ce31267
--- /dev/null
+++
b/regression-test/suites/external_table_p0/hive/test_hive_use_meta_cache.groovy
@@ -0,0 +1,102 @@
+// 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.
+
+suite("test_hive_use_meta_cache",
"p0,external,hive,external_docker,external_docker_hive") {
+
+ String enabled = context.config.otherConfigs.get("enableHiveTest")
+ if (enabled == null || !enabled.equalsIgnoreCase("true")) {
+ logger.info("disable Hive test.")
+ return;
+ }
+
+ for (String hivePrefix : ["hive3", "hive3"]) {
+ setHivePrefix(hivePrefix)
+ try {
+ String hms_port = context.config.otherConfigs.get(hivePrefix +
"HmsPort")
+ String hdfs_port = context.config.otherConfigs.get(hivePrefix +
"HdfsPort")
+ String catalog = "test_${hivePrefix}_use_meta_cache"
+ String externalEnvIp =
context.config.otherConfigs.get("externalEnvIp")
+
+ sql """drop catalog if exists ${catalog}"""
+ sql """create catalog if not exists ${catalog} properties (
+ 'type'='hms',
+ 'hive.metastore.uris' =
'thrift://${externalEnvIp}:${hms_port}',
+ 'fs.defaultFS' = 'hdfs://${externalEnvIp}:${hdfs_port}',
+ 'use_meta_cache' = 'true'
+ );"""
+
+ // create from Doris, the cache will be filled immediately
+ String database= "test_use_meta_cache_db"
+ String table = "test_use_meta_cache_tbl"
+ String database_hive = "test_use_meta_cache_db_hive"
+ String table_hive = "test_use_meta_cache_tbl_hive"
+ sql "switch ${catalog}"
+ sql "drop database if exists ${database}"
+ sql "drop database if exists ${database_hive}"
+ order_qt_sql01 "show databases like '%${database}%'";
+ sql "drop database if exists ${database}"
+ sql "create database ${database}"
+ order_qt_sql02 "show databases like '%${database}%'";
+ sql "use ${database}"
+ sql "create table ${table} (k1 int)"
+ order_qt_sql03 "show tables"
+ sql "drop table ${table}"
+ order_qt_sql04 "show tables"
+ sql "drop database ${database}"
+ order_qt_sql05 "show databases like '%${database}%'";
+
+ // create from Hive, the cache has different behavior
+ order_qt_sql01 "show databases like '%${database_hive}%'";
+ hive_docker "drop database if exists ${database_hive}"
+ hive_docker "create database ${database_hive}"
+ // not see
+ order_qt_sql02 "show databases like '%${database_hive}%'";
+ // but can use
+ sql "use ${database_hive}"
+ sql "refresh catalog ${catalog}"
+ // can see
+ order_qt_sql03 "show databases like '%${database_hive}%'";
+ // show tables first to fill cache
+ order_qt_sql04 "show tables"
+ hive_docker "create table ${database_hive}.${table_hive} (k1 int)"
+ // not see
+ order_qt_sql05 "show tables"
+ // but can select
+ sql "select * from ${table_hive}"
+ // still not see
+ order_qt_sql06 "show tables"
+ sql "refresh database ${database_hive}"
+ // can see
+ order_qt_sql07 "show tables"
+ hive_docker "drop table ${database_hive}.${table_hive}"
+ // still can see
+ order_qt_sql08 "show tables"
+ sql "refresh database ${database_hive}"
+ // can not see
+ order_qt_sql09 "show tables"
+ hive_docker "drop database ${database_hive}"
+ // still can see
+ order_qt_sql10 "show databases like '%${database_hive}%'";
+ sql "refresh catalog ${catalog}"
+ // can not see
+ order_qt_sql11 "show databases like '%${database_hive}%'";
+ } finally {
+ }
+ }
+}
+
+
diff --git
a/regression-test/suites/external_table_p0/hive/write/test_hive_write_partitions.groovy
b/regression-test/suites/external_table_p0/hive/write/test_hive_write_partitions.groovy
index 0435a68b09a..cd0533d00d9 100644
---
a/regression-test/suites/external_table_p0/hive/write/test_hive_write_partitions.groovy
+++
b/regression-test/suites/external_table_p0/hive/write/test_hive_write_partitions.groovy
@@ -191,7 +191,7 @@ suite("test_hive_write_partitions",
"p0,external,hive,external_docker,external_d
String enabled = context.config.otherConfigs.get("enableHiveTest")
if (enabled == null || !enabled.equalsIgnoreCase("true")) {
- logger.info("diable Hive test.")
+ logger.info("disable Hive test.")
return;
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]