前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Hive优化器原理与源码解析系列--优化规则ProjectOverIntersectRemoveRule(九)

Hive优化器原理与源码解析系列--优化规则ProjectOverIntersectRemoveRule(九)

作者头像
用户7600169
发布2022-04-25 15:32:54
3770
发布2022-04-25 15:32:54
举报
文章被收录于专栏:BigDataplusBigDataplus

目录

背景

优化规则ProjectOverIntersectRemoveRule

  • matches方法逻辑详解
  • onMatch方法逻辑详解

总结

背景

这篇文章来Hive优化规则ProjectOverIntersectRemoveRule,此优化规则的主要功能是把操作符树中INTERSECT交集操作符的之上的Project投影操作符,在满足一定条件下,把Project投影操作符移除减少执行计划的执行成本。

Hive CBO基于成本优化器原理与源码解析的系列文章都是基于Hive 2.3.3版本的,支持Intersect操作符(因为Hive 1.X不支持Intersect操作符),讲解ProjectOverIntersectRemoveRule才有意义。

从SQL角度讲,带有INTERSECT交集、 PROJECT投影的这种SQL语句写法中,如果Project投影中的RexNode表达式和Intersect交集操作符中RexNode行表达式的个数和数据类型完全一致,则将Intersect之上的Project投影操作符移除。

举例说明:

代码语言:javascript
复制
SELECT key, value, ds FROM (
 SELECT key, value, ds FROM src_intersect_1
 INTERSECT
 SELECT key, value, ds FROM src_intersect_2
 INTERSECT
 SELECT key, value, ds FROM src_intersect_3
) subq ;

为了说明方便,使用了SQL进行讲述,其实优化器内部使用的RelNode关系表达式构造的操作符树组成来构建的。从操作符树角度来看,最外层的Select就是顶层的Project投影操作,内部的表src_intersect_1、src_intersect_1和src_intersect_1之间的Intersect操作就是指底部的INTERSECT操作符。

变换后的SQL表示为:

代码语言:javascript
复制
SELECT key, value, ds FROM src_intersect_1
 INTERSECT
 SELECT key, value, ds FROM src_intersect_2
 INTERSECT
 SELECT key, value, ds FROM src_intersect_3;

说明:因为Project投影的字段key, value, ds和Intersect的字段key, value, ds字段个数和数据类型完全相同,因此把重复的顶层的Project操作移除掉。

Hive几乎所有优化规则Rule继承了父类RelOptRule。关于RelOptRule和RelOptRuleCall相关概念。这里不再赘述,详细翻阅前期文章。

优化规则ProjectOverIntersectRemoveRule

此优化规则的matches判断方法和OnMatch等价转换部分都相对比较简单。

因为matches和OnMatch两个方法是每条优化规则的关键,这里还是做一些两个方法的简要说明

1)matches方法逻辑详解

matches方法返回此规则Rule是否可能与给定的操作数operands匹配,但是此方法的任何实现都可以给出误报,也就是说虽然规则与操作数匹配,但随后具OnMatch(ReloptRuleCall)而不生成任何后续任务。

call.rel(0)表示为顶层为Project投影,call.rel(1)表达为顶部的Intersect交集,isTrivial函数是判断project和intersect是否完全一致,包含字段个数和字段的数据类型返回boolean值。

代码语言:javascript
复制
public boolean matches(RelOptRuleCall call) {
  Project project = call.rel(0);
  Intersect intersect = call.rel(1);
  return isTrivial(project, intersect); //判断project和intersect字段个数和数据类型是否完全一致。返回true,完全一致。可以移除
}

isTrivial方法实现,是比较Project和Intersect操作符的的字段,RexUtil.isIdentity返回表达式列表是否投影传入字段

代码语言:javascript
复制
private static boolean isTrivial(Project project, Intersect intersect) {
  return RexUtil.isIdentity(project.getProjects(), intersect.getRowType());
}

RexUtil.isIdentity方法源码实现:

比较了行表达式列表大小和字段的个数,并且用containIdentity方法内遍历了RexNode行表达式列表元素和RelDataType行数据类型的每个元素数据类型。Litmus为当有效性测试成功或失败时调用的回调。Litmus.IGNORE选择的是忽略。

代码语言:javascript
复制
 public static boolean isIdentity(List<? extends RexNode> exps,
                                   RelDataType inputRowType) {
    return inputRowType.getFieldCount() == exps.size()
            && containIdentity(exps, inputRowType, Litmus.IGNORE);
  }

2)onMatch方法逻辑详解

接收有关一条规则匹配的通知。同时此方法被调用,call.rels保存了与规则Rule的操作数Operands匹配上的关系表达式RelNode集合;call.rels[0]是根表达式。通常一条规则Rule会检查这些节点是否有效匹配,创建一个新表达式RelNode(等价的)然后调用RelOptRuleCall.transformTo(org.apache.calcite.rel.RelNode, java.util.Map<org.apache.calcite.rel.RelNode, org.apache.calcite.rel.RelNode>)注册表达式。而RelOptRuleCall用一系列RelNode关系表达式集合作为参数,对RelOptRule优化规则的调用。

代码语言:javascript
复制
public void onMatch(RelOptRuleCall call) {
    call.transformTo(call.rel(1));
  } //如果Project和Intersect字段相同,则移除Project

此条优化规则的onMatch方法设计相对简单,满足了matches判断后,直接跳过表示为顶层的Project投影call.rel(0),直接把call.rel(1) Intersect操作符注册到等价集合。这样意味着把Project进行移除。

总结

优化规则ProjectOverIntersectRemoveRule相对比较简单,简单的matches方法判断满足顶部为Project投影操作符,底部为Intersect交集操作符,并两者的字段个数和数据类型完全一致,使用call.transformTo(call.rel(1))跳过顶部Project投影,把Intersect交集操作符注册到等价集合,达到Project投影移除来进行优化目的。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 BigDataplus 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档