【问题标题】:How to deal with DISTINCT with salt如何用盐处理 DISTINCT
【发布时间】:2012-08-24 14:20:19
【问题描述】:

我遵循了来自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,它与没有盐计算的结果会有很大的不同。

有什么解决办法吗?如果先过滤,会花费很多 JOIN 工作,并且会降低性能。

【问题讨论】:

    标签: hadoop apache-pig


    【解决方案1】:

    为此,您需要在 mid_set.yyy 和 salt 之间建立多对一关系,以便将来自不同行的 mid_set.yyy 的相同值映射到相同的 salt 值。如果不是,那么 mid_set.yyy 的值将出现在 GROUP pymt BY (key, salt) 生成的不同包中,在不同的盐中存在 DISTINCT,因此在最终汇总中多次包含。这就是为什么在使用盐和 COUNT of DISTINCT 时会得到错误结果的原因。

    一种简单的方法是用 mid_set.yyy 本身替换 salt,或者编写一个 UDF/静态方法,通过计算 mid_set.yyy 的哈希值并做 mod N 来计算 salt,其中 N 可以是 1 到无穷大,以获得最佳分布N 应该是一个素数。

    【讨论】:

      【解决方案2】:

      感谢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 整数,可以使用 hash 将字符串或其他转换为整数

      【讨论】:

        猜你喜欢
        • 2016-11-28
        • 2018-11-09
        • 2020-01-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-28
        • 2011-01-01
        相关资源
        最近更新 更多