Calcite基础

1.结构基础

  在整个SQL解析过程中,在优化阶段,SQL的表示形式是逻辑节点树,这个阶段有两个核心的类,RelNode和RexNode,都是Calcite中的定义
RelNode,关系表达式,表现为TableScan、Project、Sort、Join等,是节点树的核心
  RexNode,注释说明为行表达式,表现为RexLiteral(常量)、RexCall(函数)、RexInputRef(输入引用)等

2.RelNode/AbstractRelNode

  RelNode是上层的基本接口,规定了一些方法;AbstractRelNode是RelNode的实现,后续的具体操作的类型都是基于AbstractRelNode的子类。
  AbstractRelNode的几个成员如下,其中rowType只有get方法没有set方式,构造函数里也没有设置的地方,在子类里设置,应该主要在Project这个实现中。

/**
 * Cached type of this relational expression.
 */
protected RelDataType rowType;

/**
 * The digest that uniquely identifies the node.
 */
@API(since = "1.24", status = API.Status.INTERNAL)
protected RelDigest digest;

private final RelOptCluster cluster;

/** Unique id of this object, for debugging. */
protected final int id;

/** RelTraitSet that describes the traits of this RelNode. */
protected RelTraitSet traitSet;
  • RelDataType
      类型信息,代表一行或一个表达式结果的数据类型信息。
  • RelDigest
      作为唯一标识使用,内容基本等同于relNode本身
  • RelOptCluster
      优化查询期间相关关系表达式的环境,汇集了Planner, RexBuilder, MetadataQuery 等各种信息,在SqlNode 转换 RelNode 前创建,后面一直充当类似上下文的作用
  • RelTraitSet
      在Calcite中没有使用不同的对象代表逻辑和物理算子,但是使用trait来表示一个算子的物理属性
      RelTrait的有序集合,RelTrait表示特征定义中关系表达特征的表现,表示RelNode的物理属性,用来定义逻辑表的物理相关属性
      RelTraitDef代表RelTrait的类型,有三种:ConventionTraitDef、RelCollationTraitDef、RelDistributionTraitDef,RelTrait的实现类基本上也就是这三个类型
      ConventionTraitDef代表转换,RelCollationTraitDef代表排序,RelDistributionTraitDef代表分布

3.LogicalJoin

  LogicalJoin的类继承关系如下,可以看到,上层还有两个父类:Join和BiRel
在这里插入图片描述

3.1.BiRel

  BiRel是所有两个input形式的关系表达式的一个基类,相对AbstractRelNode来说,多了两个成员:左右输入。

protected RelNode left;
protected RelNode right;

  UML图如下
在这里插入图片描述

3.2.Join

  Join形式的一个基类,主要添加了如下几个成员

protected final RexNode condition;
protected final ImmutableSet<CorrelationId> variablesSet;
protected final ImmutableList<RelHint> hints;

/**
 * Values must be of enumeration {@link JoinRelType}, except that
 * {@link JoinRelType#RIGHT} is disallowed.
 */
protected final JoinRelType joinType;

protected final JoinInfo joinInfo;

  variablesSet和hints是附加的参数和提示,普通状态下都为空,暂不关注。
  condition是条件表达式,RexNode类型
  JoinInfo,记录join操作的信息,三个成员:leftKeys、rightKeys、nonEquiConditions。分别记录该join使用到的左右子树列集合和非相等条件
  joinType,join的类型,有INNER、LEFT、RIGHT、FULL、SEMI、ANTI
  SEMI类型对应的形态如下

* SELECT * FROM EMP
* WHERE EXISTS (SELECT 1 FROM DEPT
*     WHERE DEPT.DEPTNO = EMP.DEPTNO)

  ANTI是SEMI的相反

SELECT * FROM EMP
* WHERE NOT EXISTS (SELECT 1 FROM DEPT
*     WHERE DEPT.DEPTNO = EMP.DEPTNO)

3.3.样例

  以如下sql语句为样例,查看LogicalJoin几个关键的成员的信息

SELECT * FROM t1 join t2 ON t1.id = t2.id AND t1.id < 1000

  condition的结果如下,代表的就是SQL的条件语句:
在这里插入图片描述

  joinType和JoinInfo信息如下
在这里插入图片描述

  rowType的信息如下,代表的就是左右子树的类信息
在这里插入图片描述

4.LogicalSort

  LogicalSort的类继承关系如下,可以看到,上层还有两个父类:Sort和SingleRel
在这里插入图片描述

4.1.SingleRel

  是所有一个input形式的关系表达式的一个基类,增加的成员就只有一个input
protected RelNode input;
  UML图如下
在这里插入图片描述

4.2.Sort

  排序相关的一个基类,增加的成员如下

public final RelCollation collation;
public final RexNode offset;
public final RexNode fetch;

  fetch是返回的数据量,使用limit语句时对应的limit的数量
  offset是返回前需要丢弃的数量,大部分为空,可以在这个上做优化,降低返回数据量
  collation是对排序的描述,最终类为RelFieldCollation,包含两个关键枚举成员:Direction、NullDirection
  Direction就是排序方式:ASCENDING(“ASC”)、STRICTLY_ASCENDING(“SASC”)、DESCENDING(“DESC”)、STRICTLY_DESCENDING(“SDESC”)、CLUSTERED(“CLU”)
SASC、SDESC与前一个的差别就是包不包含相等的值,ASC是正向排序,后一个可以等于前一个;SASC后一个大于前一个
CLU没有特性顺序,使用Hash排序一般会出现这种排序方式
  NullDirection代表null的排序,应该就是null放在什么位置,因为null值不能比较:FIRST、LAST、UNSPECIFIED。UNSPECIFIED表示未指定

4.3.样例

  以如下sql语句为样例,查看LogicalSort几个关键的成员的信息

SELECT id FROM t1 ORDER BY id LIMIT 3

  collation结果如下
在这里插入图片描述

  fetch和offset结果如下
在这里插入图片描述

5.LogicalFilter

  LogicalFilter继承自Filter,再往上是就是SingleRel

5.1.Filter

  过滤器,有一个成员

protected final RexNode condition;

  condition就是过滤条件

5.2.LogicalFilter

  增加了一个成员

private final ImmutableSet<CorrelationId> variablesSet;

5.3.样例

  以如下sql语句为样例,查看LogicalFilter几个关键的成员的信息

SELECT id FROM t1 where t1.id < 1000

  condition结果如下
在这里插入图片描述

  input结果如下
在这里插入图片描述

6.LogicalTableScan

  LogicalTableScan继承自TableScan,直接继承自AbstractRelNode

6.1.TableScan

  成员如下

protected final RelOptTable table;
protected final ImmutableList<RelHint> hints;

  主要是table,表示表的信息

6.2.RelOptTableImpl

  RelOptTable的实现之一,主要成员如下

private final RelOptSchema schema;
private final RelDataType rowType;
private final Table table;
private final Function<Class, Expression> expressionFunction;
private final ImmutableList<String> names;

/** Estimate for the row count, or null.
 *
 * <p>If not null, overrides the estimate from the actual table.
 *
 * <p>Useful when a table that contains a materialized query result is being
 * used to replace a query expression that wildly underestimates the row
 * count. Now the materialized table can tell the same lie. */
private final Double rowCount;

6.3.TableSourceTable

  Flink对RelOptTable的实现,目前Flink的解析最后都是走到TableSourceTable上的,扩展自Calcite的Prepare.AbstractPreparingTable
  结构如下

class TableSourceTable(
    relOptSchema: RelOptSchema,
    rowType: RelDataType,
    statistic: FlinkStatistic,
    val tableSource: DynamicTableSource,
    val isStreamingMode: Boolean,
    val contextResolvedTable: ContextResolvedTable,
    val flinkContext: FlinkContext,
    val abilitySpecs: Array[SourceAbilitySpec] = Array.empty)
  extends FlinkPreparingTableBase(

  relOptSchema代表一组关系数据集,Flink实现了CalciteCatalogReader接口,用于读取表元数据使用
  rowType数据各列的类型信息
  statistic表统计信息
  tableSource数据表类,可以转换为Calcite表
  isStreamingMode是否流模式
  contextResolvedTable解析表,解析该表源来自哪里。有三种表类型:永久表、临时表、匿名表
  flinkContext上下文信息,包含一些相关配置之类的

6.4.样例

  以如下sql语句为样例,查看LogicalFilter几个关键的成员的信息

SELECT id FROM t1 where t1.id < 1000

  首先看整体结构,在TableScan上面封装了一层Project
在这里插入图片描述

  table使用的类是TableSourceTable,内容如下
在这里插入图片描述

  relOptSchema结构如下
在这里插入图片描述

  statistic结构如下
在这里插入图片描述

  tableSource的结构如下
在这里插入图片描述

  contextResolvedTable结构如下
在这里插入图片描述

  flinkContext结构如下
在这里插入图片描述

7.LogicalProject

  继承自Project,上层是SingleRel,核心就是在Project里的一个成员

protected final ImmutableList<RexNode> exps;
protected final ImmutableList<RelHint> hints;

  exps对应的应该就是其input所返回的列信息。继续以如下sql语句为样例,查看LogicalProject的关键信息

SELECT id FROM t1 where t1.id < 1000

  在两个不同的节点上的LogicalProject,可以看到其exps的信息不一样
  首先input是LogicalTableScan的,其exps有三列,就是LogicalTableScan的返回
在这里插入图片描述

  之后input是LogicalFilter的,因为只返回一列,所以exps就是一列
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值