Calcite分析 -- Register

Calcite Version:1.26.0

  

ensureRegistered

getSubset,从mapRel2Subset中查询一下是否注册过

无注册调用register

equivRel不为空,需要merge的case,参考,https://www.cnblogs.com/fxjwind/p/15220576.html

 

register

处理一下当有equivRel的情况下,可以直接用其的RelSet

调用registerImpl

 

registerImpl

1. 保证Rel的所有Input都完成register,这步完成,所有input节点都完成注册

rel = rel.onRegister(this);

 

2. Digest

所以这里记录下digest,用于找出equivExp,这样就可以直接返回

 

 

3. 创建新的RelSet,加入allSets,这时的RelSet是空的

 

4. registerClass(rel);

把rel的class和convention,加到如下的结构中,并register

 

5. addRelToSet(rel, set);

这个函数非常重要,

第一个,把subset注册到RelSet中, 

其中RelSet.add,会调用到getOrCreateSubset

这个本身逻辑比较简单,就是如果相应的traits的subset不存在,就创建一个新的

其中有一段和converter相关的逻辑比较难理解,放到conventer的部分讲解吧。

RelSet.add -> getOrCreateSubset -> subset.add(rel) -> set.addInternal(rel) -> rels.add(rel)

看下这个调用链,印证我一直的怀疑,Calcite经常会刻意增加代码的阅读成本:-)

第一步的结果,

 

"select mgr, count(*) from sales.emp group by mgr order by mgr desc nulls last limit 5"

这里可以简单看一下,Calcite中的核心概念的关系,对于这么简单的一个SQL

最终生成,4个RelNode,当前都是logical算子,带limit的Sort,Aggre,Project,TableScan

这里为他们生成4个RelSubset,通过mapRel2Subset,给找到RelNode对应的RelSubset,注意这里是按地址map;RelSubSet代表一组RelTraits,比如这里的,NONE.[0 DESC...]

但如果要从RelSubSet找RelNode,就需要通过subset.set.Rel去找到,很麻烦

同时对应的生成4个RelSet,等价集合,这里就是要把SubSet(带有一组特殊物理属性,traits,的等价集合)加到RelSet中,

所以RelSet中,

包含一组等价的RelNodes,rels;

一组SubSets,subsets;

 

第二是propagateCostImprovements,由于加入新的subset,要计算他的cost,并且还要看看所有parent的best是不是会发生变化

这个放在单独的分析cost的部分讨论;

第三是ruleDriver.onProduce(rel, subset),由于加入新的subset,可能需要增加新的Task来explore

这个放在分析TopDown引擎的部分讨论;

 

6. 设置parents

就是把所有input对应的RelSet的parents中加上自己,这个是和input是反向的链接,bottom-up;input是Top-down

 

 

7. fireRules

从classOperands中拿出所有和这个class相关的operand,这是在addRule时候提前生成的,避免这里要遍历所有的operand

  

如果可以match,调用onMatch

 

最终针对这个logicalSort,fire的rules有5个,

 

posted on 2021-08-30 19:30  fxjwind  阅读(458)  评论(0)    收藏  举报