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