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