dremio 存储插件查找&home space&用户创建space处理简单说明

dremio中space或者home 中的view 实际后边都会转换到实际存储插件对应的table,只是处理上少有不同

整体简单处理

核心是dremio 通过apache calcite 的sql 校验中的处理,catalogreader 是自己的实现DremioCatalogReader,里边需要通过
PlannerCatalog 进行table 的check (实际的getValidatedTableWithSchema 方法)

  • 参考方法
  public DremioTable getValidatedTableWithSchema(NamespaceKey key) {
    return convertView(metadataCatalog.getTableForQuery(key));
  }

注意: 其中获取到table之后还会进行一个convertView 转换,核心是将viewtable (vds)转换为实际上的物理执行(calcite type)

  • convertView 简单处理
    dremio 是转换为了一个convertedViewTable,因为实际一个viewtable 可能是多个物理表的关联,
protected DremioTable convertView(DremioTable table) {
    if (table == null || !(table instanceof ViewTable)) {
      return table;
    }
 
    ViewTable viewTable = (ViewTable) table;
    Pair<CatalogIdentity, VersionedPath> viewCacheKey = Pair.of(viewTable.getViewOwner(),
      VersionedPath.of(viewTable.getPath().getPathComponents(), viewTable.getVersionContext()));
    ConvertedViewTable convertedViewTable = convertedViewTables.get(viewCacheKey);
    if (convertedViewTable == null) {
      DremioToRelContext.DremioQueryToRelContext context = DremioToRelContext.createQueryContext(converter);
      RelRoot root = context.expandView(viewTable);
 
      final RelDataType validatedRowTypeWithNames;
      if (viewTable.getView().hasDeclaredFieldNames()) {
        final List<String> fieldNames = viewTable.getView().getFieldNames();
        final List<RelDataTypeField> validatedFields = root.validatedRowType.getFieldList();
        Preconditions.checkState(fieldNames.size() == validatedFields.size(),
          String.format("Cardinality mismatch between view field names %s and converted field list %s",
            fieldNames, root.validatedRowType.getFullTypeString()));
        List<RelDataTypeField> fields = new ArrayList<>();
        for (int i = 0; i < validatedFields.size(); i++) {
          final RelDataTypeField field = validatedFields.get(i);
          fields.add(new RelDataTypeFieldImpl(fieldNames.get(i), field.getIndex(), field.getType()));
        }
        validatedRowTypeWithNames = new RelRecordType(fields);
      } else {
        validatedRowTypeWithNames = root.validatedRowType;
      }
      convertedViewTable = ConvertedViewTable.of(viewTable, validatedRowTypeWithNames, root.rel);
      if (converter.getSettings().getOptions().getOption(VDS_CACHE_ENABLED)) {
        convertedViewTables.put(viewCacheKey, convertedViewTable);
      }
    }
    return convertedViewTable;
  }

存储插件source 的查找

这个相对比较简单,dremio 对于创建完成的source 插件,source 名称就是后边查找的存储插件,应该到代码中就是sql node 会转换为一个namespacekey
key 的root 就是source 名称(对应dremio ManagedStoragePlugin 的name)

  • 参考处理
    DatasetManager 类中
 public DremioTable getTable(
      NamespaceKey key,
      MetadataRequestOptions options,
      boolean ignoreColumnCount
      ){
 
    final DatasetConfig config = getConfig(key);
 
    if(config != null) {
      // canonicalize the path.
      key = new NamespaceKey(config.getFullPathList());
    }
 
    if(isAmbiguousKey(key)) {
      key = getCanonicalKey(key);
    }
 
    String pluginName = key.getRoot();
    //  PluginRetriever 接口实现进行具体的查找
    final ManagedStoragePlugin plugin = plugins.getPlugin(pluginName, false);
 
    if (config == null) {
      logger.debug("Got a null config");
    } else {
      logger.debug("Got config id {}", config.getId());
    }

CatalogServiceImpl(实现了PluginRetriever接口)中对于getPlugin 的处理

  public ManagedStoragePlugin getPlugin(String name, boolean synchronizeOnMissing) {
    // 对于home 特殊处理了
    final String pluginName = (name.startsWith("@")) ? "__home" : name;
    // Preconditions.checkState(isCoordinator);
 
    if (!synchronizeOnMissing) {
      // get from in-memory
      return getPlugins().get(pluginName);
    }
   // 详细的可以查看实际源码
    // if plugin is missing in-memory, we will synchronize to kvstore
    return CatalogServiceImpl.this.getPlugin(pluginName, true);
  }

space 中的处理

space 并更没有什么特殊的,只是dremio 自己抽象了一层,比较适合进行数据的工程化管理,这部分dremio 实际上并不能直接知道是什么
类型的,只是先查找plugin source,如果查找不到就认为可能是view 的vds

  • 参考处理
    DatasetManager 类中的处理
public DremioTable getTable(
      NamespaceKey key,
      MetadataRequestOptions options,
      boolean ignoreColumnCount
      ){
 
    final DatasetConfig config = getConfig(key);
 
    if(config != null) {
      // canonicalize the path.
      key = new NamespaceKey(config.getFullPathList());
    }
 
    if(isAmbiguousKey(key)) {
      key = getCanonicalKey(key);
    }
 
    String pluginName = key.getRoot();
    final ManagedStoragePlugin plugin = plugins.getPlugin(pluginName, false);
 
    if (config == null) {
      logger.debug("Got a null config");
    } else {
      logger.debug("Got config id {}", config.getId());
    }
 
    if(plugin != null) {
 
      // if we have a plugin and the info isn't a vds (this happens in home, where VDS are intermingled with plugin datasets).
      if(config == null || config.getType() != DatasetType.VIRTUAL_DATASET) {
        return getTableFromPlugin(key, config, plugin, options, ignoreColumnCount);
      }
    }
 
    if(config == null) {
      return null;
    }
 
    // at this point, we should only be looking at virtual datasets.
    if(config.getType() != DatasetType.VIRTUAL_DATASET) {
      // if we're not looking at a virtual dataset, it must mean that we hit a race condition where the source has been removed but the dataset was retrieved just before.
      return null;
    }
   //  vds 数据处理
    return createTableFromVirtualDataset(config, options);
  }

createTableFromVirtualDataset 参考处理

  private ViewTable createTableFromVirtualDataset(DatasetConfig datasetConfig, MetadataRequestOptions options) {
    try {
      // 1.4.0 and earlier didn't correctly save virtual dataset schema information.
      BatchSchema schema = DatasetHelper.getSchemaBytes(datasetConfig) != null ? CalciteArrowHelper.fromDataset(datasetConfig) : null;
 
      View view = Views.fieldTypesToView(
        Iterables.getLast(datasetConfig.getFullPathList()),
        datasetConfig.getVirtualDataset().getSql(),
        ViewFieldsHelper.getViewFields(datasetConfig),
        datasetConfig.getVirtualDataset().getContextList(),
        options.getSchemaConfig().getOptions() != null && options.getSchemaConfig().getOptions().getOption(FULL_NESTED_SCHEMA_SUPPORT) ? schema : null
      );
 
      return new ViewTable(new NamespaceKey(datasetConfig.getFullPathList()), view,
        identityProvider.getOwner(datasetConfig.getFullPathList()),
        datasetConfig, schema);
    } catch (Exception e) {
      throw new RuntimeException(String.format("Failure while constructing the ViewTable from datasetConfig for key %s with datasetId %s",
        String.join(".", datasetConfig.getFullPathList()),
        datasetConfig.getId().getId()),
        e);
    }
  }

但是实际view 是不能直接执行的,dremio 对于view 还会进行转换到实际的物理执行(calcite type) 也就是上边整体说明中提到的

说明

以上是一个对于dremio vds space 以及存储插件source 查找处理的一个简单说明,详细的可以多阅读源码,vds 是dremio 中一个比较强大的功能
可以实现灵活的数据模型处理

参考资料

sabot/kernel/src/main/java/com/dremio/exec/ops/PlannerCatalogImpl.java
sabot/kernel/src/main/java/com/dremio/exec/catalog/CatalogImpl.java
sabot/kernel/src/main/java/com/dremio/exec/catalog/PluginRetriever.java
sabot/kernel/src/main/java/com/dremio/exec/catalog/DatasetManager.java
sabot/kernel/src/main/java/com/dremio/exec/catalog/CatalogServiceImpl.java
sabot/kernel/src/main/java/com/dremio/exec/planner/logical/ConvertedViewTable.java

posted on 2024-02-28 08:00  荣锋亮  阅读(8)  评论(0编辑  收藏  举报

导航