aliyun/aliyun-odps-java-sdk

关于ODPS中mapreduce的疑问

wangsir1988 opened this issue · 6 comments

关于ODPS中mapreduce的使用,我这边有两个疑问。

  1. 如果map的输出中Key有多个列c1, c2, c3. 如果仅指定c1为group columns。那么假设map生成了两个数据(k1, v1), (k2, v2)。其中k1.c1 = k2.c1。 那最终reduce函数接收到的Key的内容为k1还是k2呢?
  2. 示例类com.aliyun.odps.mapred.open.example.Join中的reduce函数,按我的理解此函数每次进入时,都只会有一个key,里面的tag也是固定的,但是代码里面对tag做了判断分支,一个逻辑写leftValues后没有使用,一个逻辑没有写就使用了leftValues,在reduce的一次访问中,两个逻辑分支只能有一个走到,leftValues也是局部变量,这个是否存在bug?

@lyman 求大神

@oyz 帮忙回答下

oyz commented

@wangsir1988
https://help.aliyun.com/document_detail/27883.html?spm=5176.doc44628.6.658.F4sOhl
通常情况下,GroupingColumns包含在KeySortColumns中,KeySortColumns和PartitionColumns要包含在Key中。
在Map端,Mapper输出的Record会根据设置的PartitionColumns计算哈希值,决定分配到哪个Reducer,会根据KeySortColumns对Record进行排序。
在Reduce端,输入Records在按照KeySortColumns排序好后,会根据GroupingColumns指定的列对输入的Records进行分组,即会顺序遍历输入的Records,把GroupingColumns所指定列相同的Records作为一次reduce函数调用的输入。
1、reduce接收到的key,就是map写出来的,不会因为设置了group column而变化
2、因为每个value,都是有自己对应的key的,所以在reduce函数中,每一次迭代,其实key里面的内容是变化的,这样,那个tag其实是变化的

@oyz 我仔细看了下,Record类型是个接口。map或reduce传入的并不是固定的数据对象而是一个接口对象。如果Record对象的内容会按照一定的规则来改变的话,我这些疑问确实都能解答。
一般的编程习惯(特别是函数式编程习惯)中。形参所代表的内容在整个函数生命周期内都不会变化。
这一点确实出乎我的意料,也是我见识太少了。多谢大神的回复了!

我见到api文档里面也提到了一句record复用的问题,不过不是很详细。
另外,这个record对象的使用,有没有详细点的规则说明,如何正确使用它呢(什么情况下他的内容会变化)?

oyz commented

@wangsir1988 在map,reduce接口里的record对象都是复用的,比如每次map调用和reduce的每次iterator的迭代,key ,value的 record对象都是同一个,但是通过record.get(i)拿到的对象内容是变化更新的。

多谢各位,问题得到完美的解答。