上一篇主要对Calcite的背景,技术特点,SQL的RBO和CBO等做了一个初步的介绍,深入浅出Calcite与SQL CBO(Cost-Based Optimizer)优化。这一篇会从Hive入手,介绍Hive如何使用Calcite来优化自己的SQL,主要从源码的角度进行介绍。文末附有一篇其他博主的文章,从其他角度阐述Hive CBO的,可供参考。
另外,上一篇中有提到我整理了Calcite的各种样例,Calcite的一些使用样例整理成到github,
最后会从Hive这个例子延伸,看看自己可以怎么借助Calcite来优化SQL。
Hive SQL执行流程
Hive debug简单介绍
在开始介绍之前,本着授人以渔的精深,先说下如何使用Hive debug查看源码执行流程。具体流程可以参照这篇:
简单说就是搭建个hive环境,通过 hive --debug -hiveconf hive.root.logger=DEBUG,console语句开启 debug 模式,开启后 hive 会监听 8000 端口并等待输入,此时从本地的 hive 源码项目中配置远程 debug 就可以通过 debug 的方式追踪 hive 执行流程。
debug过程中,执行SQL的入口是在CliDriver.executeDriver()这个方法,可以在这个地方打一个断点,然后就可以调试跟踪了。如下图:
搭建hive服务的话,建议使用docker,搭建起来会比较方便一些。
PS:这里介绍用的Hive的版本是2.3.x。
Hive SQL执行流程
前面说到,debug输入语句的入口的类是org.apache.hadoop.hive.cli.CliDriver。而实际执行SQL语句逻辑的主要模块是ql(Query Language) 模块的Driver类(org.apache.hadoop.hive.ql.Driver)。Driver主要逻辑,是先调用compile(String command, boolean resetTaskIds, boolean deferClose)方法,对 SQL 进行编译,然后Driver调用execute()方法,执行对应的MR任务。我们的关注点主要放在compile()方法的执行过程。
在compile()方法中,整个SQL执行流程如下图:
即先将SQL解析成AST Node,然后转换成QB,再转换成Operator tree,最后进行逻辑优化和物理优化后,就编程一个可执行的MR任务了。对应阶段的入口,我也在上面的图中标注出来了。
其中较为核心的,从AST Node到Phsical Optimize这几个阶段,都是在SemanticAnalyzer.analyzeInternal()方法中进行的。这个方法中的注释已经跟我们说明了SQL执行的主要流程,我这里贴一下:Generate Resolved Parse tree from syntax tree
Gen OP Tree from resolved Parse Tree
Deduce Resultset Schema
Generate Parse Context for Optimizer & Physical compiler
Take care of view creation
Generate table access stats if required
Perform Logical optimization
Generate column access stats if required - wait until column pruning takes place during optimization
Optimize Physical op tree & Translate to target execution engine (MR, TEZ..)
put accessed columns to readEntity
if desired check we're not going over partition scan limits
大致的流程和图里面介绍的差不多,不过会多一些细节上的补充ÿ