我从alexeipab那里得到了帮助How to handle spill memory in pig,它确实很好用,但我现在有另一个问题,相同的示例代码:
pymt = LOAD 'pymt' USING PigStorage('|') AS ($pymt_schema);
pymt_grp_with_salt = GROUP pymt BY (key,salt)
results_with_salt = FOREACH pymt_grp {
--distinct
mid_set = FILTER pymt BY xxx=='abc';
mid_set_result = DISTINCT mid_set.yyy;
result = COUNT(mid_set_result)
}
pymt_grp = GROUP results_with_salt BY key;
result = FOREACH pymt_grp {
GENERATE SUM(results_with_salt.result); --it is WRONG!!
}
我不能在该组中使用sum,它与不使用salt计算的结果非常不同。
有什么解决方案吗?如果先过滤,则会花费很多JOIN作业,并降低性能。
答案 0 :(得分:1)
为了实现这一点,你需要在mid_set.yyy和salt之间建立多对一的关系,这样来自不同行的mid_set.yyy的相同值将被映射到相同的salt值。如果不是,那么mid_set.yyy的值将出现在GROUP pymt BY(key,salt)生成的不同包中,在不同的盐中存活DISTINCT,因此在最终汇总中包含多次。这就是为什么在使用salt和COUNT的DISTINCT时可能会得到错误的结果。
一种简单的方法可以是用mid_set.yyy本身替换salt,或者编写一个UDF /静态方法,通过获取mid_set.yyy的哈希来计算salt,并执行mod N,其中N可以是1到无穷大,以获得最佳分布N应该是素数。
答案 1 :(得分:0)
感谢alexeipab,你给我一个很大的帮助,我的工作如下
pymt = LOAD 'pymt' USING PigStorage('|') AS ($pymt_schema);
pymt = FOREACH pymt GENERATE *, (yyy%$prime_num) as salt;
pymt_grp_with_salt = GROUP pymt BY (key,salt);
它有效!!
如果yyy是num integer,则可以使用hash将字符串或其他字符串转换为整数