This is an automated email from the ASF dual-hosted git repository.
jshao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/main by this push:
new fbdb14f083 [#6744] improvment(core): Batch get metadata objects for
TagMetaService (#6752)
fbdb14f083 is described below
commit fbdb14f0835be9945cf8cda03854e753058eb274
Author: Mini Yu <[email protected]>
AuthorDate: Sat Apr 5 01:40:18 2025 +0800
[#6744] improvment(core): Batch get metadata objects for TagMetaService
(#6752)
### What changes were proposed in this pull request?
Group by metadata object by metadata type and batch get all metadata
with the same type.
### Why are the changes needed?
To return the times to access databases and improve performance.
Fix: #6744
### Does this PR introduce _any_ user-facing change?
N/A
### How was this patch tested?
Test locally and existing tests.
---
.../relational/mapper/TableColumnMapper.java | 3 +
.../mapper/TableColumnSQLProviderFactory.java | 4 +
.../provider/base/TableColumnBaseSQLProvider.java | 33 ++++
.../relational/service/MetadataObjectService.java | 189 +++++++--------------
.../relational/service/RoleMetaService.java | 21 +--
.../storage/relational/service/TagMetaService.java | 40 +++--
6 files changed, 129 insertions(+), 161 deletions(-)
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/TableColumnMapper.java
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/TableColumnMapper.java
index 87b38ea482..64859c5921 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/TableColumnMapper.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/TableColumnMapper.java
@@ -71,4 +71,7 @@ public interface TableColumnMapper {
@SelectProvider(type = TableColumnSQLProviderFactory.class, method =
"selectColumnPOById")
ColumnPO selectColumnPOById(@Param("columnId") Long columnId);
+
+ @SelectProvider(type = TableColumnSQLProviderFactory.class, method =
"listColumnPOsByColumnIds")
+ List<ColumnPO> listColumnPOsByColumnIds(@Param("columnIds") List<Long>
columnIds);
}
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/TableColumnSQLProviderFactory.java
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/TableColumnSQLProviderFactory.java
index 11f0d5419f..a0e7655e2b 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/TableColumnSQLProviderFactory.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/TableColumnSQLProviderFactory.java
@@ -90,4 +90,8 @@ public class TableColumnSQLProviderFactory {
public static String selectColumnPOById(@Param("columnId") Long columnId) {
return getProvider().selectColumnPOById(columnId);
}
+
+ public static String listColumnPOsByColumnIds(@Param("columnIds") List<Long>
columnIds) {
+ return getProvider().listColumnPOsByColumnIds(columnIds);
+ }
}
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/TableColumnBaseSQLProvider.java
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/TableColumnBaseSQLProvider.java
index 1ed117b8da..0b59855023 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/TableColumnBaseSQLProvider.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/TableColumnBaseSQLProvider.java
@@ -132,4 +132,37 @@ public class TableColumnBaseSQLProvider {
+ " WHERE column_id = #{columnId} AND deleted_at = 0"
+ " ORDER BY table_version DESC LIMIT 1";
}
+
+ public String listColumnPOsByColumnIds(@Param("columnIds") List<Long>
columnIds) {
+ return "<script>"
+ + " SELECT c.column_id AS columnId, c.column_name AS columnName,"
+ + " c.column_position AS columnPosition, c.metalake_id AS metalakeId,
c.catalog_id AS catalogId,"
+ + " c.schema_id AS schemaId, c.table_id AS tableId,"
+ + " c.table_version AS tableVersion, c.column_type AS columnType,"
+ + " c.column_comment AS columnComment, c.column_nullable AS nullable,"
+ + " c.column_auto_increment AS autoIncrement,"
+ + " c.column_default_value AS defaultValue, c.column_op_type AS
columnOpType,"
+ + " c.deleted_at AS deletedAt, c.audit_info AS auditInfo"
+ + " FROM "
+ + TableColumnMapper.COLUMN_TABLE_NAME
+ + " c "
+ + "JOIN ("
+ + " SELECT column_id, MAX(table_version) AS max_version"
+ + " FROM "
+ + TableColumnMapper.COLUMN_TABLE_NAME
+ + " WHERE column_id IN ("
+ + " <foreach collection='columnIds' item='columnId'
separator=','>"
+ + " #{columnId}"
+ + " </foreach>"
+ + " ) AND deleted_at = 0 GROUP BY column_id"
+ + ") latest "
+ + "ON c.column_id = latest.column_id AND c.table_version =
latest.max_version"
+ + " WHERE c.column_id IN ("
+ + "<foreach collection='columnIds' item='columnId' separator=','>"
+ + "#{columnId}"
+ + "</foreach>"
+ + ") "
+ + " AND c.deleted_at = 0"
+ + "</script>";
+ }
}
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/service/MetadataObjectService.java
b/core/src/main/java/org/apache/gravitino/storage/relational/service/MetadataObjectService.java
index 188c06ac23..8ecc218626 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/service/MetadataObjectService.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/service/MetadataObjectService.java
@@ -20,17 +20,19 @@ package org.apache.gravitino.storage.relational.service;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.Function;
import java.util.stream.Collectors;
-import javax.annotation.Nullable;
import org.apache.gravitino.MetadataObject;
import org.apache.gravitino.storage.relational.mapper.CatalogMetaMapper;
import org.apache.gravitino.storage.relational.mapper.FilesetMetaMapper;
import org.apache.gravitino.storage.relational.mapper.MetalakeMetaMapper;
import org.apache.gravitino.storage.relational.mapper.ModelMetaMapper;
import org.apache.gravitino.storage.relational.mapper.SchemaMetaMapper;
+import org.apache.gravitino.storage.relational.mapper.TableColumnMapper;
import org.apache.gravitino.storage.relational.mapper.TableMetaMapper;
import org.apache.gravitino.storage.relational.mapper.TopicMetaMapper;
import org.apache.gravitino.storage.relational.po.CatalogPO;
@@ -57,6 +59,18 @@ public class MetadataObjectService {
private static final Logger LOG =
LoggerFactory.getLogger(MetadataObjectService.class);
+ static final Map<MetadataObject.Type, Function<List<Long>, Map<Long,
String>>>
+ TYPE_TO_FULLNAME_FUNCTION_MAP =
+ ImmutableMap.of(
+ MetadataObject.Type.METALAKE,
MetadataObjectService::getMetalakeObjectsFullName,
+ MetadataObject.Type.CATALOG,
MetadataObjectService::getCatalogObjectsFullName,
+ MetadataObject.Type.SCHEMA,
MetadataObjectService::getSchemaObjectsFullName,
+ MetadataObject.Type.TABLE,
MetadataObjectService::getTableObjectsFullName,
+ MetadataObject.Type.FILESET,
MetadataObjectService::getFilesetObjectsFullName,
+ MetadataObject.Type.MODEL,
MetadataObjectService::getModelObjectsFullName,
+ MetadataObject.Type.TOPIC,
MetadataObjectService::getTopicObjectsFullName,
+ MetadataObject.Type.COLUMN,
MetadataObjectService::getColumnObjectsFullName);
+
private MetadataObjectService() {}
public static long getMetadataObjectId(
@@ -105,134 +119,6 @@ public class MetadataObjectService {
throw new IllegalArgumentException(String.format("Doesn't support the type
%s", type));
}
- // Metadata object may be null because the metadata object can be deleted
- // asynchronously.
- @Nullable
- public static String getMetadataObjectFullName(String type, long
metadataObjectId) {
- MetadataObject.Type metadataType = MetadataObject.Type.valueOf(type);
- String fullName = null;
- long objectId = metadataObjectId;
-
- do {
- switch (metadataType) {
- case METALAKE:
- MetalakePO metalakePO =
MetalakeMetaService.getInstance().getMetalakePOById(objectId);
- if (metalakePO != null) {
- fullName = metalakePO.getMetalakeName();
- metadataType = null;
- } else {
- return null;
- }
- break;
-
- case CATALOG:
- CatalogPO catalogPO =
CatalogMetaService.getInstance().getCatalogPOById(objectId);
- if (catalogPO != null) {
- fullName =
- fullName != null
- ? DOT_JOINER.join(catalogPO.getCatalogName(), fullName)
- : catalogPO.getCatalogName();
- metadataType = null;
- } else {
- return null;
- }
- break;
-
- case SCHEMA:
- SchemaPO schemaPO =
SchemaMetaService.getInstance().getSchemaPOById(objectId);
- if (schemaPO != null) {
- fullName =
- fullName != null
- ? DOT_JOINER.join(schemaPO.getSchemaName(), fullName)
- : schemaPO.getSchemaName();
- objectId = schemaPO.getCatalogId();
- metadataType = MetadataObject.Type.CATALOG;
- } else {
- return null;
- }
- break;
-
- case TABLE:
- TablePO tablePO =
TableMetaService.getInstance().getTablePOById(objectId);
- // if fullName is null:
- // fullName = catalogPO.getSchemaName(),schemaPO.getTableName()
- if (tablePO != null) {
- fullName =
- fullName != null
- ? DOT_JOINER.join(tablePO.getTableName(), fullName)
- : tablePO.getTableName();
- objectId = tablePO.getSchemaId();
- metadataType = MetadataObject.Type.SCHEMA;
- } else {
- return null;
- }
- break;
-
- case TOPIC:
- TopicPO topicPO =
TopicMetaService.getInstance().getTopicPOById(objectId);
- if (topicPO != null) {
- fullName =
- fullName != null
- ? DOT_JOINER.join(topicPO.getTopicName(), fullName)
- : topicPO.getTopicName();
- objectId = topicPO.getSchemaId();
- metadataType = MetadataObject.Type.SCHEMA;
- } else {
- return null;
- }
- break;
-
- case FILESET:
- FilesetPO filesetPO =
FilesetMetaService.getInstance().getFilesetPOById(objectId);
- if (filesetPO != null) {
- fullName =
- fullName != null
- ? DOT_JOINER.join(filesetPO.getFilesetName(), fullName)
- : filesetPO.getFilesetName();
- objectId = filesetPO.getSchemaId();
- metadataType = MetadataObject.Type.SCHEMA;
- } else {
- return null;
- }
- break;
-
- case MODEL:
- ModelPO modelPO =
ModelMetaService.getInstance().getModelPOById(objectId);
- if (modelPO != null) {
- fullName =
- fullName != null
- ? DOT_JOINER.join(modelPO.getModelName(), fullName)
- : modelPO.getModelName();
- objectId = modelPO.getSchemaId();
- metadataType = MetadataObject.Type.SCHEMA;
- } else {
- return null;
- }
- break;
-
- case COLUMN:
- ColumnPO columnPO =
TableColumnMetaService.getInstance().getColumnPOById(objectId);
- if (columnPO != null) {
- fullName =
- fullName != null
- ? DOT_JOINER.join(columnPO.getColumnName(), fullName)
- : columnPO.getColumnName();
- objectId = columnPO.getTableId();
- metadataType = MetadataObject.Type.TABLE;
- } else {
- return null;
- }
- break;
-
- default:
- throw new IllegalArgumentException(
- String.format("Doesn't support the type %s", metadataType));
- }
- } while (metadataType != null);
-
- return fullName;
- }
-
/**
* Retrieves a map of Metalake object IDs to their full names.
*
@@ -389,6 +275,51 @@ public class MetadataObjectService {
return tableIdAndNameMap;
}
+ /**
+ * Retrieves a map of column object IDs to their full names.
+ *
+ * @param columnsIds A list of column object IDs to fetch names for.
+ * @return A Map where the key is the column ID and the value is the column
full name. The map may
+ * contain null values for the names if its parent object is deleted.
Returns an empty map if
+ * no column objects are found for the given IDs. {@code @example} value
of table full name:
+ * "catalog1.schema1.table1.column1"
+ */
+ public static Map<Long, String> getColumnObjectsFullName(List<Long>
columnsIds) {
+ List<ColumnPO> columnPOs =
+ SessionUtils.getWithoutCommit(
+ TableColumnMapper.class, mapper ->
mapper.listColumnPOsByColumnIds(columnsIds));
+
+ if (columnPOs == null || columnPOs.isEmpty()) {
+ return new HashMap<>();
+ }
+
+ List<Long> tableIds =
columnPOs.stream().map(ColumnPO::getTableId).collect(Collectors.toList());
+ Map<Long, String> tableIdAndNameMap = getTableObjectsFullName(tableIds);
+
+ HashMap<Long, String> columnIdAndNameMap = new HashMap<>();
+
+ columnPOs.forEach(
+ columnPO -> {
+ // since the table can be deleted, we need to check the null value,
+ // and when the table is deleted, we will set fullName of column to
+ // null
+ String tableName =
tableIdAndNameMap.getOrDefault(columnPO.getTableId(), null);
+ if (tableName == null) {
+ LOG.warn(
+ "The table '{}' of column '{}' may be deleted",
+ columnPO.getTableId(),
+ columnPO.getColumnId());
+ columnIdAndNameMap.put(columnPO.getColumnId(), null);
+ return;
+ }
+
+ String fullName = DOT_JOINER.join(tableName,
columnPO.getColumnName());
+ columnIdAndNameMap.put(columnPO.getColumnId(), fullName);
+ });
+
+ return columnIdAndNameMap;
+ }
+
/**
* Retrieves a map of Topic object IDs to their full names.
*
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
b/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
index 59ec4dea8c..58e4a6e7fc 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
@@ -19,7 +19,6 @@
package org.apache.gravitino.storage.relational.service;
import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.io.IOException;
@@ -364,28 +363,10 @@ public class RoleMetaService {
.map(SecurableObjectPO::getMetadataObjectId)
.collect(Collectors.toList());
- Map<MetadataObject.Type, Function<List<Long>, Map<Long, String>>>
- objectFullNameGetterFnMap =
- ImmutableMap.of(
- MetadataObject.Type.METALAKE,
- MetadataObjectService::getMetalakeObjectsFullName,
- MetadataObject.Type.CATALOG,
- MetadataObjectService::getCatalogObjectsFullName,
- MetadataObject.Type.SCHEMA,
- MetadataObjectService::getSchemaObjectsFullName,
- MetadataObject.Type.TABLE,
- MetadataObjectService::getTableObjectsFullName,
- MetadataObject.Type.FILESET,
- MetadataObjectService::getFilesetObjectsFullName,
- MetadataObject.Type.MODEL,
- MetadataObjectService::getModelObjectsFullName,
- MetadataObject.Type.TOPIC,
- MetadataObjectService::getTopicObjectsFullName);
-
// dynamically calling getter function based on type
Map<Long, String> objectIdAndNameMap =
Optional.of(MetadataObject.Type.valueOf(type))
- .map(objectFullNameGetterFnMap::get)
+
.map(MetadataObjectService.TYPE_TO_FULLNAME_FUNCTION_MAP::get)
.map(getter -> getter.apply(objectIds))
.orElseThrow(
() ->
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/service/TagMetaService.java
b/core/src/main/java/org/apache/gravitino/storage/relational/service/TagMetaService.java
index 5863877ae7..3b2c6d42e2 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/service/TagMetaService.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/service/TagMetaService.java
@@ -24,6 +24,7 @@ import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -230,19 +231,34 @@ public class TagMetaService {
mapper.listTagMetadataObjectRelsByMetalakeAndTagName(metalakeName, tagName));
List<MetadataObject> metadataObjects = Lists.newArrayList();
- for (TagMetadataObjectRelPO po : tagMetadataObjectRelPOs) {
- String fullName =
- MetadataObjectService.getMetadataObjectFullName(
- po.getMetadataObjectType(), po.getMetadataObjectId());
-
- // Metadata object may be deleted asynchronously when we query the
name, so it will return
- // null. We should skip this metadata object.
- if (fullName == null) {
- continue;
+ Map<String, List<TagMetadataObjectRelPO>> tagMetadataObjectRelPOsByType =
+ tagMetadataObjectRelPOs.stream()
+
.collect(Collectors.groupingBy(TagMetadataObjectRelPO::getMetadataObjectType));
+
+ for (Map.Entry<String, List<TagMetadataObjectRelPO>> entry :
+ tagMetadataObjectRelPOsByType.entrySet()) {
+ String metadataObjectType = entry.getKey();
+ List<TagMetadataObjectRelPO> rels = entry.getValue();
+
+ List<Long> metadataObjectIds =
+ rels.stream()
+ .map(TagMetadataObjectRelPO::getMetadataObjectId)
+ .collect(Collectors.toList());
+ Map<Long, String> metadataObjectNames =
+ MetadataObjectService.TYPE_TO_FULLNAME_FUNCTION_MAP
+ .get(MetadataObject.Type.valueOf(metadataObjectType))
+ .apply(metadataObjectIds);
+
+ for (Map.Entry<Long, String> metadataObjectName :
metadataObjectNames.entrySet()) {
+ String fullName = metadataObjectName.getValue();
+
+ // Metadata object may be deleted asynchronously when we query the
name, so it will
+ // return null, we should skip this metadata object.
+ if (fullName != null) {
+ metadataObjects.add(
+ MetadataObjects.parse(fullName,
MetadataObject.Type.valueOf(metadataObjectType)));
+ }
}
-
- MetadataObject.Type type =
MetadataObject.Type.valueOf(po.getMetadataObjectType());
- metadataObjects.add(MetadataObjects.parse(fullName, type));
}
return metadataObjects;