山大软工实践hive(3)-算子做了什么

2021SC@SDUSC

山大软工实践hive(3)-算子做了什么

目标

上一篇初步知道算子是什么,这一篇需要深入了解各算子

各算子

TS

扫描表以获取数据,但实际是Hadoop完成的表数据读取,该算子的作用是把从底层获取的数据传输给子节点处理

SEL

用于投影操作,对应select语句

FIL

用于投影,对应sql 的where语句

RS

mapReduce中间有个shuffle过程,实现map结果到reduce任务的映射采集,而RS算子实现了类似shuffle的功能,包括了数据采集(运用算法把数据分配给不同的reduce任务),排序方式(对数据按照key排序),输出数据

GBY

对应groupby

hive实现了两种聚合方式,而GBY基于这两种实现
1.hash聚合,用hash表把key值相同的数据聚合在一起(在读取表数据的时候通过hash表完成计算,避免了排序),不需要进行shuffle操作,但是只能做局部聚合,用于map端减少数据量,对应GBY->RS->GBY中第一个GBY
2.sort聚合,通过RS算子对数据排序分组,让具有相同key的数据被分到一组,然后对每组数据聚合。对应GBY->RS->GBY中第二个GBY

如果同时用groupby 与 orderby,则计算会用sort聚合(顺便排序)

基于hash聚合的实现


散列因子=散列条目数/总数,如果小于定的最小值(如0.5),则代表聚集效果不好,(如0.5时平均每个散列条目对应2条数据),则需要放弃hash转而使用sort聚合,这是用hashAggr变量区分。然后就进行局部聚合。对应下面的代码

在GBY process方法中的一段
 if (numRowsHashTbl > numRowsInput * minReductionHashAggr) {
          LOG.warn("Disable Hash Aggr: #hash table = " + numRowsHashTbl
              + " #total = " + numRowsInput + " reduction = " + 1.0
              * (numRowsHashTbl / numRowsInput) + " minReduction = "
              + minReductionHashAggr);
          flushHashTable(true);
          hashAggr = false;
          }
          
在 processKey方法中一段
 if (hashAggr) {
      newKeys.setHashKey();
      processHashAggr(row, rowInspector, newKeys);  对应hash聚合
    } else {
      processAggr(row, rowInspector, newKeys);  对应sort聚合
    }
基于sort聚合的实现


currentKey为groupby 分组中该分组的key值,newKey则是每次父节点传的条目对应的key值,也就是说,一旦newKey!=currentKey,就代表该组已完成,可以输出结果。反之,不断合并输入的局部聚合的结果
在process方法中进行了对newKeys的计算,而在processAggr中,进行了currentKey与newKey的比较,代码如下

processAggr中
boolean keysAreEqual = (currentKeys != null && newKeys != null)?
        newKeys.equals(currentKeys) : false;
        
    if (currentKeys != null && !keysAreEqual) {
      
      if (!conf.isDontResetAggrsDistinct()) {
        forward(currentKeys.getKeyArray(), aggregations);
        countAfterReport = 0;
      }
    }
实际过程

hashGBY负责把数据分开地进行局部聚合,通过RS算子 传输给sortGBY,然后全局聚合得到结果,比如

select id,count(word) from a group by id

元组形式如(0,a),(1,b)


这解释了为什么会有GBY->RS->GBY的结构

关于局部聚合

比如原本聚合数据中有相同key的数据,在key前面加上数字变成如1_key,2_key,再对这些数据聚合,得到(1_key,value1),(2_key,value2)。这一部分是局部聚合
之后去除前面部分,变成(key,value1),(key,value2),再对数据聚合,得到最终结果。这部分是全局聚合
之所以要这样两阶段聚合,是为了防止数据倾斜(给某个任务节点分配的数据太多,导致性能下降)
上面是一种实现方式,至于hive应该是直接把数据分发给不同的map节点进行聚合,而不需要添加字段内容

JOIN

对应表的join运算


RS对数据分组排序,并且加上标签以区分数据来自哪个表,然后再由join算子进行join运算

不过JOIN算子有很多种如CommonJoinOperator,CommonMergeJoinOperator等等,这将在下一节区分

下一步

算子源码分析得并不详细,因为一难以找到上层谁调用该方法,二找到了也不知道上层在干嘛,三是变量方法太多了,如果不参考别人博客的解析,实在寸步难行。所以下一步做什么主要看参考博客下一步做什么。

参考

魔鬼_的博客

jiayuanv_127的博客

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值