如何从 JDBC Adapter SchemaFactory 链接规划器?
How to chain planners from JDBC Adapter SchemaFactory?
我扩展了 JDBC 适配器并使用了一个 model.json 配置自定义模式工厂,其中包含 1 个原始模式和 2 个派生模式来添加规则并且有效,规则在规划期间在原始模式上执行,但是他们的最终结果并没有被 Volcano 规划者选为最佳选择,因为它太贵了。规则转换 RelNode 以在 2 个派生模式上执行。下面和代码中有更多详细信息。
1) 我可以告诉 Volcano planner 忽略我通过自定义 JDBC SchemaFactory 传递的 3 个模式中的 1 个吗?
我希望解析器在该 1 个原始模式上工作,但规划器永远不要在该模式(仅其他 2 个派生模式)中建议最佳(最便宜)计划。 1 个原始模式总是与其他 2 个派生模式一对一映射,因此我的规则 returns 的 RelNode 在语义上总是等价的,只是更昂贵(安全原因)。
2) 如果那行不通,我如何才能调用 HepPlanner 而不是从 model.json 中设置的 SchemaFactory 调用默认的 Volcano 规划器,因为那是我的起点?
您可以在 GitHub 上找到我的全部代码,我将其公开,以便每个人都可以比我更好地开始使用 Calcite。
这里是 link: https://github.com/igrgurina/multicloud_rewriter
Calcite 库很棒,但很难入门,因为它缺少常见任务的示例和教程。
理想情况下,我会让 HepPlanner 执行我的规则,将它们转换为使用 2 个派生模式而不是 1 个原始模式的语义等效表达式(我有一个规则可以做到这一点),然后让 Volcano planner 优化它只使用出于安全原因,2 个派生模式,不知道存在 1 个原始模式。
我还没有找到任何合理的例子来演示如何做到这一点,所以任何帮助将不胜感激(请不要 post links 到 Druid 示例或 Apache Calcite 文档网站, 我经历了他们一千次)。
我已经设法通过使用 Hook.PROGRAM
并在我的自定义程序之前执行我的规则来完成这项工作。
由于 Hook
在 Calcite
库中被标记为 for testing and debugging only
,我想说这不是应该如何完成的,但目前我没有更好的办法。
这是一个带有代码示例的简短摘要:
public static class MultiCloudHookManager {
private static final Program PROGRAM = new MultiCloudProgram();
private static Hook.Closeable globalProgramClosable;
public static void addHook() {
if (globalProgramClosable == null) {
globalProgramClosable = Hook.PROGRAM.add(program());
}
}
private static Consumer<Holder<Program>> program() {
return prepend(PROGRAM);
}
// this doesn't have to be in the separate program
private static Consumer<Holder<Program>> prepend(Program program) {
return (holder) -> {
if (holder == null) {
throw new IllegalStateException("No program holder");
}
Program chain = holder.get();
if (chain == null) {
chain = Programs.standard();
}
holder.set(Programs.sequence(program, chain));
};
}
}
然后在SchemaFactory
中使用MultiCloudHookManager
,您只需调用MultiCloudHookManager.addHook()
方法即可。在这种情况下,MultiCloudHookManager.PROGRAM
设置为 MultiCloudProgram
,它只是执行 HepPlanner
.
中的一组规则
有关详细信息,请参阅 the source code in GitHub repository。
此 hack 解决方案的灵感来自 another library。
我扩展了 JDBC 适配器并使用了一个 model.json 配置自定义模式工厂,其中包含 1 个原始模式和 2 个派生模式来添加规则并且有效,规则在规划期间在原始模式上执行,但是他们的最终结果并没有被 Volcano 规划者选为最佳选择,因为它太贵了。规则转换 RelNode 以在 2 个派生模式上执行。下面和代码中有更多详细信息。
1) 我可以告诉 Volcano planner 忽略我通过自定义 JDBC SchemaFactory 传递的 3 个模式中的 1 个吗?
我希望解析器在该 1 个原始模式上工作,但规划器永远不要在该模式(仅其他 2 个派生模式)中建议最佳(最便宜)计划。 1 个原始模式总是与其他 2 个派生模式一对一映射,因此我的规则 returns 的 RelNode 在语义上总是等价的,只是更昂贵(安全原因)。
2) 如果那行不通,我如何才能调用 HepPlanner 而不是从 model.json 中设置的 SchemaFactory 调用默认的 Volcano 规划器,因为那是我的起点?
您可以在 GitHub 上找到我的全部代码,我将其公开,以便每个人都可以比我更好地开始使用 Calcite。
这里是 link: https://github.com/igrgurina/multicloud_rewriter
Calcite 库很棒,但很难入门,因为它缺少常见任务的示例和教程。
理想情况下,我会让 HepPlanner 执行我的规则,将它们转换为使用 2 个派生模式而不是 1 个原始模式的语义等效表达式(我有一个规则可以做到这一点),然后让 Volcano planner 优化它只使用出于安全原因,2 个派生模式,不知道存在 1 个原始模式。
我还没有找到任何合理的例子来演示如何做到这一点,所以任何帮助将不胜感激(请不要 post links 到 Druid 示例或 Apache Calcite 文档网站, 我经历了他们一千次)。
我已经设法通过使用 Hook.PROGRAM
并在我的自定义程序之前执行我的规则来完成这项工作。
由于 Hook
在 Calcite
库中被标记为 for testing and debugging only
,我想说这不是应该如何完成的,但目前我没有更好的办法。
这是一个带有代码示例的简短摘要:
public static class MultiCloudHookManager {
private static final Program PROGRAM = new MultiCloudProgram();
private static Hook.Closeable globalProgramClosable;
public static void addHook() {
if (globalProgramClosable == null) {
globalProgramClosable = Hook.PROGRAM.add(program());
}
}
private static Consumer<Holder<Program>> program() {
return prepend(PROGRAM);
}
// this doesn't have to be in the separate program
private static Consumer<Holder<Program>> prepend(Program program) {
return (holder) -> {
if (holder == null) {
throw new IllegalStateException("No program holder");
}
Program chain = holder.get();
if (chain == null) {
chain = Programs.standard();
}
holder.set(Programs.sequence(program, chain));
};
}
}
然后在SchemaFactory
中使用MultiCloudHookManager
,您只需调用MultiCloudHookManager.addHook()
方法即可。在这种情况下,MultiCloudHookManager.PROGRAM
设置为 MultiCloudProgram
,它只是执行 HepPlanner
.
有关详细信息,请参阅 the source code in GitHub repository。
此 hack 解决方案的灵感来自 another library。