如何在方解石中将项目、过滤器、聚合下推到 TableScan

How to push down project, filter, aggregation to TableScan in Calcite

我正在使用Apache Calcite 实现分布式OLAP 系统,数据源是RDBMS。所以我想把RelNode树中的project/filter/aggregation下推到MyTableScan extends TableScan。在MyTableScan中,一个RelBuilder得到推入RelNode。最后,RelBuilder生成对源数据库的Query。同时,原RelNode树中的project/filter/aggregation需要移动或修改。

据我所知,Calcite 不支持此功能。

Current limitations: The JDBC adapter currently only pushes down table scan operations; all other processing (filtering, joins, aggregations and so forth) occurs within Calcite. Our goal is to push down as much processing as possible to the source system, translating syntax, data types and built-in functions as we go. If a Calcite query is based on tables from a single JDBC database, in principle the whole query should go to that database. If tables are from multiple JDBC sources, or a mixture of JDBC and non-JDBC, Calcite will use the most efficient distributed query approach that it can.

在我看来,RelOptRule可能是一个不错的选择。不幸的是,当我创建新的RelOptRule时,我不能轻易找到父节点来删除一个节点。

RelOptRule是个不错的选择?任何人有实现此功能的好主意吗?

谢谢。

创建一个新的 RelOptRule 是正确的方法。请注意,您不应该尝试直接删除规则内的任何节点。相反,您匹配包含要替换的节点的子树(例如,TableScan 顶部的 Filter)。然后用下推过滤器的等效节点替换整个子树。

这通常是通过创建符合特定适配器调用约定的相关操作的子类来处理的。例如,在 Cassandra 适配器中,有一个 CassandraFilterRule 匹配 CassandraTableScan 之上的 LogicalFilterconvert 函数然后构造一个 CassandraFilter 实例。 CassandraFilter 实例设置必要的信息,以便在实际发出查询时,过滤器可用。

浏览一些 Cassandra、MongoDB 或 Elasticsearch 适配器的代码可能会有所帮助,因为它们比较简单。我还建议将其添加到邮件列表中,因为您可能会在那里获得更详细的建议。

我创建了一些 RelOptRule 来下推 Project/Filter/Aggregate RelNode 上层 TableScan。也许对其他人有帮助。

RelOptRule用于定义一些规则来匹配整个RelNode中的子树。匹配时,调用onMatch方法做一些事情。

onMatch方法中,我们可以新建一个RelNode,调用transformTo方法替换匹配到的子树。

例如:

Project
  |
Filter
  |
TableScan

PushDownFilter规则如下:

  public class PushDownFilter extends RelOptRule {

  public PushDownFilter(RelOptRuleOperand operand, String description) {
    super(operand, "Push_down_rule:" + description);
  }

  public static final PushDownFilter INSTANCE =
      new PushDownFilter(
          operand(
              Filter.class,
              operand(TableScan.class, none())),
          "filter_tableScan");

  @Override
  public void onMatch(RelOptRuleCall call) {
    LogicalFilter filter = (LogicalFilter) call.rels[0];
    TableScan tableScan = (TableScan) call.rels[1];
    // push down filter
    call.transformTo(tableScan);
  }
}

这条规则将匹配Filter->TableScan子树,然后调用onMatch方法。该方法只有transformTo tableScan。结果就是把Filter->TableScan换成了TableScan,整个RelNode如下:

Project
  |
TableScan

注意新RelNode的RelDataType必须等于匹配的子树

方解石支持一些规则使用,例如FilterJoinRuleFilterTableScanRule等。