当前位置:   article > 正文

hive优化:让一个MR做更多的事情_如何让hive任务只跑一个mr

如何让hive任务只跑一个mr
常常会有类似这样的需求:
数据是这样的
user_id  int      用户ID        
pay_channel int   充值渠道ID
pay_cents   int   充值金额
user_id+pay_channel为唯一键
求每个用户充值金额最多的渠道。


直观上有两种思路:
1. 先求每个用户在所有渠道上的最大充值,然后回表join
select t1.user_id , t1.pay_channel 
from table t1 join
(
    select user_id , max(pay_cents) max_pay from table group by user_id
) t2 on (t1.user_id = t2.user_id and t1.pay_cents = t2.max_pay)  ;


2.用先分析函数对pay_cent做排名标记,再用排名来过滤
select user_id , pay_channel from 
(
    select 
        user_id , pay_channel , rank(pay_cents)over)(partition by user_id ) rk
    from table 
) t1 
where rk = 1 ;




上面两个方法都需要两个MR来完成。
根据Hive的特性,我们可以有第三种思路,通过UDAF用一个MR完成。
select user_id , getKeyWithMaxValue(pay_channel , pay_cents) max_channels 
from table 
group by user_id ;


getKeyWithMaxValue(key , value)是我自定义的UDAF,用来求最大value所对应的key,这样的key可能是多个,所以返回值是list.


UDAF实现代码如下:

  1. public class GetKeyWithMaxValue extends UDAF {
  2. public static class GetKeyWithMaxValue_int_int implements UDAFEvaluator{
  3. //最终结果
  4. private HashMap<Integer , Integer > result;
  5. //负责初始化计算函数并设置它的内部状态,result是存放最终结果的
  6. @Override
  7. public void init() {
  8. result= new HashMap<Integer , Integer >() ;
  9. }
  10. //每次对一个新值进行聚集计算都会调用iterate方法
  11. public boolean iterate(Integer key , Integer value)
  12. {
  13. if (result == null )
  14. result=new HashMap<Integer , Integer >();
  15. if(result.containsKey(key))
  16. {
  17. int new_value = result.get(key) ;
  18. if (new_value < value)
  19. new_value = value ;
  20. result.put(key , new_value) ;
  21. }
  22. else
  23. result.put( key , value ) ;
  24. return true;
  25. }
  26. //Hive需要部分聚集结果的时候会调用该方法
  27. //会返回一个封装了聚集计算当前状态的对象
  28. public HashMap<Integer , Integer > terminatePartial()
  29. {
  30. return result;
  31. }
  32. //合并两个部分聚集值会调用这个方法
  33. public boolean merge(HashMap<Integer , Integer > other)
  34. {
  35. //将 result和other合并
  36. Iterator<Entry<Integer, Integer>> iter = other.entrySet().iterator();
  37. while (iter.hasNext()) {
  38. Map.Entry<Integer , Integer> entry = iter.next();
  39. int key = entry.getKey();
  40. int val = entry.getValue();
  41. if(result.containsKey(key))
  42. {
  43. int new_value = result.get(key) ;
  44. if (new_value < val)
  45. new_value = val ;
  46. result.put(key , new_value) ;
  47. }
  48. else
  49. result.put( key , val ) ;
  50. }
  51. return true ;
  52. }
  53. //Hive需要最终聚集结果时候会调用该方法
  54. public ArrayList<Integer> terminate()
  55. {
  56. ArrayList<Integer> res = new ArrayList<Integer>() ;
  57. //先找出最大的value
  58. int max_value = Integer.MIN_VALUE ;
  59. Iterator<Entry<Integer, Integer>> iter = result.entrySet().iterator();
  60. while (iter.hasNext()) {
  61. Map.Entry<Integer , Integer> entry = iter.next();
  62. int val = entry.getValue();
  63. if (val > max_value)
  64. max_value = val ;
  65. }
  66. Iterator<Entry<Integer, Integer>> iter2 = result.entrySet().iterator();
  67. while (iter2.hasNext()) {
  68. Map.Entry<Integer , Integer> entry = iter2.next();
  69. int key = entry.getKey();
  70. int val = entry.getValue();
  71. if (val == max_value)
  72. res.add(key) ;
  73. }
  74. return res ;
  75. }
  76. }
  77. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/976869
推荐阅读
相关标签
  

闽ICP备14008679号