(hadoop学习-1)mapreduce实现数据过滤、聚合与排序

https://blog.csdn.net/xuefei2/article/details/51655798

翻译:http://blog.ditullio.fr/2015/12/24/hadoop-basics-filter-aggregate-sort-mapreduce/

数据源:
对样例数据集Donations进行过滤、聚合与排序操作。数据来自donaorschoose。解压缩后是一个1.5G的CSV文件,共460万行记录。具体详见官方网站(http://data.donorschoose.org/open-data/overview/)。
注意,
1)该数据集的换行符格式是CR/LF。在linux下,需要首先删除CR格式(\r,0x0D),并对换行符(CR)所在的上下两行合并。具体可以使用perl。
perl -pe ’s/\\\\\n/ /;’ filename
2)该数据集每个字段结果都有双引号,字符串分割时需要留意分割字符。
3)主要数据字段说明
_donationid
_projectid
_donor_acctid
_cartid

donor_city
donor_state
donor_zip: 因隐私原因,最后两位隐藏
is_teacher_acct: 教师发起的捐献

donation_timestamp
dollar_amount
donation_included_optional_support

payment_included_acct_credit
payment_included_campaign_gift_card
payment_included_web_purchased_gift_card

via_giving_page: 通过特定活动开展的捐献
for_honoree: 包括被捐献人的活动
thank_you_packet_mailed:

查询要求:
查询对所有捐赠者不是教师的记录,按照城市对捐赠金额汇总,输出城市名、捐赠金额,并按照捐赠金额排降序。城市名不区分大小写。
  1. <span style="font-size:14px;"><span style="font-size:18px;"><span style="font-size:14px;">SELECT SUM(dollar_amount) as sumtotal, UPPER(donor_city) as city  
  2. FROM donations  
  3. WHERE is_teacher_acct != 't'  
  4. GROUP BY UPPER(donor_city)  
  5. ORDER BY sumtotal DESC;</span></span></span>  

解决方案:
利用chain mapreduce,依次执行两个mapreduce Job。第一个Job抽取donor_city(城市名)、total(捐赠金额)字段,并按照城市名实现捐赠金额聚合,实现数据过滤、聚合;第二个Job,按照捐赠金额排降序。

- 第一个Job Mapper:抽取donor_city(城市名)、total(捐赠金额)字段。
- 第一个Job Combiner:按照donor_city,累加该filesplit的total。减少中间数据传送。
- 第一个Job Reducer: 按照donor_city,累加total。输出数据存储为donor_city、total。
- 第二个Job Mapper:读入第一个Job Reducer输出结果,交换key、value,输出total、donor_city。
- 第二个Job Reducer:自定义sortComparator,实现double按照降序排序。经过shuffle排序后,输出排降序的total、donor_city。

注意事项:
1、对内置数据类型,如DoubleWritable,自定义排序顺序时候,可以使用sortComparatorClass()。通过自定义排序类,继承自对应数据类型,实现排序。
2、chain mapreduce,上一个job的输出文件(存放在hdfs),直接作为下一个job的输入文件。
3、对于可能的异常,可以使用Mrunit进行测试。

执行结果:
$ hdfs dfs -cat output/donation-price/p* |head -n 20
3514021.3 New York
2328154.0 San Francisco
815354.1 Seattle
677975.6 Chicago
508308.2 West Berlin
500588.5 Los Angeles
447923.0 Brooklyn
418111.1 Oklahoma City
343251.9 Indianapolis
215072.7 Framingham
209319.9 Springfield
158270.3 Charlotte
153875.1 San Ramon
149707.1 Washington
131766.5 Tulsa
119922.8 Raleigh
115334.9 Houston
108732.2 Baltimore
101028.8 Dallas

==========donation job1==========

User:     xuefei
Name:     donation-job1
Application Type:     MAPREDUCE
Application Tags:     
YarnApplicationState:     FINISHED
FinalStatus Reported by AM:     SUCCEEDED
Started:     星期五 五月 13 09:24:57 +0800 2016
Elapsed:     57sec
Tracking URL:     History
Diagnostics:     

        Map input records=4631337
        Map output records=1502321
        Map output bytes=27150482
        Map output materialized bytes=2375954
        Input split bytes=1632
        Combine input records=1502321
        Combine output records=115926
        Reduce input groups=24224
        Reduce shuffle bytes=2375954
        Reduce input records=115926
        Reduce output records=24224  //压缩了80%记录数,减少shuffle数据量
        Spilled Records=231852
        Shuffled Maps =12 //共12个split,启动12个Map进程
        Failed Shuffles=0
        Merged Map outputs=12
        GC time elapsed (ms)=6325
        CPU time spent (ms)=93630
        Physical memory (bytes) snapshot=3480043520
        Virtual memory (bytes) snapshot=10956181504
        Total committed heap usage (bytes)=2666004480

==========donation job2==========

User:     xuefei
Name:     donation-job2
Application Type:     MAPREDUCE
Application Tags:     
YarnApplicationState:     FINISHED
FinalStatus Reported by AM:     SUCCEEDED
Started:     星期五 五月 13 09:25:56 +0800 2016
Elapsed:     21sec
Tracking URL:     History
Diagnostics:     


        Map input records=24224
        Map output records=24224
        Map output bytes=454936
        Map output materialized bytes=503390
        Input split bytes=132
        Combine input records=0
        Combine output records=0
        Reduce input groups=5990
        Reduce shuffle bytes=503390
        Reduce input records=24224
        Reduce output records=24224
        Spilled Records=48448
        Shuffled Maps =1
        Failed Shuffles=0
        Merged Map outputs=1
        GC time elapsed (ms)=62
        CPU time spent (ms)=4010
        Physical memory (bytes) snapshot=451493888
        Virtual memory (bytes) snapshot=1703575552
        Total committed heap usage (bytes)=402653184

程序代码:
[java] view plain copy
  1. <span style="font-size:14px;"><span style="font-size:18px;"><span style="font-size:14px;">package donation1;  
  2.   
  3. import java.io.DataInput;  
  4. import java.io.DataOutput;  
  5. import java.io.IOException;  
  6.   
  7. import org.apache.hadoop.conf.Configuration;  
  8. import org.apache.hadoop.conf.Configured;  
  9. import org.apache.hadoop.fs.Path;  
  10. import org.apache.hadoop.io.DoubleWritable;  
  11. import org.apache.hadoop.io.LongWritable;  
  12. import org.apache.hadoop.io.Text;  
  13. import org.apache.hadoop.io.WritableComparable;  
  14. import org.apache.hadoop.io.WritableComparator;  
  15. import org.apache.hadoop.mapreduce.Job;  
  16. import org.apache.hadoop.mapreduce.Mapper;  
  17. import org.apache.hadoop.mapreduce.Reducer;  
  18. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;  
  19. import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;  
  20. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
  21. import org.apache.hadoop.mapreduce.lib.output.SequenceFileOutputFormat;  
  22. import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;  
  23. import org.apache.hadoop.util.StringUtils;  
  24. import org.apache.hadoop.util.Tool;  
  25. import org.apache.hadoop.util.ToolRunner;  
  26.   
  27. import donation1.Donation.Descdouble;  
  28.   
  29. public class Donation extends Configured implements Tool {  
  30.   
  31.   
  32.      //自定义sortComparatorClass,对第二个job实现按照total排降序  
  33.     public static class Descdouble extends WritableComparator {  
  34.   
  35.         public Descdouble() {  
  36.             super(DoubleWritable.classtrue);  
  37.             // TODO Auto-generated constructor stub  
  38.         }  
  39.   
  40.         @Override  
  41.         public int compare(WritableComparable a, WritableComparable b) {  
  42.             // TODO Auto-generated method stub  
  43.             DoubleWritable lhs=(DoubleWritable)a;  
  44.             DoubleWritable rhs=(DoubleWritable)b;  
  45.             return ((rhs.get()-lhs.get())>0)?1:-1;  
  46.         }  
  47.   
  48.     }  
  49.   
  50.     public static class Djob2mapper extends  
  51.             Mapper<LongWritable, Text, DoubleWritable, Text>{  
  52.         DoubleWritable outputKey=new DoubleWritable();  
  53.         Text outputValue=new Text();  
  54.         @Override  
  55.         protected void map(LongWritable key, Text value,  
  56.                 Context context)  
  57.                 throws IOException, InterruptedException {  
  58.             // TODO Auto-generated method stub  
  59.             String []words=StringUtils.split(value.toString(), '\t');  
  60.             outputKey.set(Double.parseDouble(words[1]));  
  61.             outputValue.set(words[0]);  
  62.             context.write(outputKey, outputValue);  
  63.         }  
  64.   
  65.     }  
  66.   
  67.     public static class Djobreducer1 extends  
  68.             Reducer<Text, DoubleWritable, Text, DoubleWritable>{  
  69.   
  70.         DoubleWritable outputValue=new DoubleWritable();  
  71.         @Override  
  72.         protected void reduce(Text key, Iterable<DoubleWritable> values,  
  73.                 Context context)  
  74.                 throws IOException, InterruptedException {  
  75.             // TODO Auto-generated method stub  
  76.             double sumtotal=0.0;  
  77.             for(DoubleWritable value:values){  
  78.                 sumtotal+=value.get();  
  79.             }  
  80.             outputValue.set(sumtotal);  
  81.             context.write(key, outputValue);  
  82.         }  
  83.   
  84.     }  
  85.   
  86.     public static class Djobmapper1 extends  
  87.             Mapper<LongWritable, Text, Text, DoubleWritable> {  
  88.         Text outputKey=new Text();  
  89.         DoubleWritable outputValue=new DoubleWritable();  
  90.         @Override  
  91.         protected void map(LongWritable key, Text value,  
  92.                 Context context)  
  93.                 throws IOException, InterruptedException {  
  94.             // TODO Auto-generated method stub  
  95.   
  96.           //对输入行按照“,”进行分列  
  97.             String []words=value.toString().split("\",\"");  
  98.   
  99.             if(words[0].equals("_donationid")||words[7].substring(11).equals("t")||words[4].isEmpty() || words[11].isEmpty())  
  100.                 return;  
  101.   
  102.             String city=words[4];  
  103.             String strprice=words[11];  
  104.             strprice=strprice.substring(1, strprice.length()-1); //删除price末尾的双引号  
  105.             Double total=Double.parseDouble(strprice);  
  106.             outputKey.set(city);  
  107.             outputValue.set(total);  
  108.   
  109.             context.write(outputKey, outputValue);  
  110.   
  111.         }  
  112.   
  113.     }  
  114.   
  115.     public int run(String []args) throws Exception{  
  116.         Job job1=Job.getInstance(getConf(), "donation-job1");  
  117.   
  118.         Configuration conf1=job1.getConfiguration();  
  119.         job1.setJarByClass(getClass());  
  120.   
  121.         FileInputFormat.setInputPaths(job1, new Path("data/donation"));  
  122.         Path out1=new Path("output/donation-city");  
  123.         out1.getFileSystem(conf1).delete(out1, true);  
  124.         FileOutputFormat.setOutputPath(job1, out1);  
  125.   
  126.         job1.setInputFormatClass(TextInputFormat.class);  
  127.         job1.setOutputFormatClass(TextOutputFormat.class);  
  128.   
  129.         job1.setMapperClass(Djobmapper1.class);  
  130.         job1.setMapOutputKeyClass(Text.class);  
  131.         job1.setMapOutputValueClass(DoubleWritable.class);  
  132.   
  133.         job1.setCombinerClass(Djobreducer1.class);  
  134.         job1.setReducerClass(Djobreducer1.class);  
  135.         job1.setOutputKeyClass(DoubleWritable.class);  
  136.         job1.setOutputValueClass(Text.class);  
  137.   
  138.         //实现chain mapreduce的关键。如果job1能够成功执行,则继续继续后面代码;否则退出。  
  139.         if(job1.waitForCompletion(true)==false)  
  140.             return 1;  
  141.   
  142.         Job job2=Job.getInstance(getConf(), "donation-job2");  
  143.         Configuration conf2=job2.getConfiguration();  
  144.         job2.setJarByClass(getClass());  
  145.   
  146.         FileInputFormat.setInputPaths(job2, out1);  
  147.         Path out2=new Path("output/donation-price");  
  148.         out2.getFileSystem(conf2).delete(out2, true);  
  149.         FileOutputFormat.setOutputPath(job2, out2);  
  150.   
  151.         job2.setInputFormatClass(TextInputFormat.class);  
  152.         job2.setOutputFormatClass(TextOutputFormat.class);  
  153.   
  154.         job2.setMapperClass(Djob2mapper.class);  
  155.         job2.setMapOutputKeyClass(DoubleWritable.class);  
  156.         job2.setMapOutputValueClass(Text.class);  
  157.         job2.setSortComparatorClass(Descdouble.class);  
  158.         job2.setReducerClass(Reducer.class);  
  159.         job2.setOutputKeyClass(DoubleWritable.class);  
  160.         job2.setOutputValueClass(Text.class);  
  161.   
  162.         return job2.waitForCompletion(true)?0:1;  
  163.     }  
  164.   
  165.     public static void main(String []args){  
  166.         int result=0;  
  167.         try{  
  168.             result=ToolRunner.run(new Configuration(), new Donation(), args);  
  169.         }catch(Exception e){  
  170.             e.printStackTrace();  
  171.         }  
  172.         System.exit(result);  
  173.     }  
  174. }  
  175.   
  176. ========Mrunit========  
  177.   
  178. package donation1test;  
  179.   
  180. import java.io.IOException;  
  181.   
  182. import org.apache.hadoop.io.DoubleWritable;  
  183. import org.apache.hadoop.io.LongWritable;  
  184. import org.apache.hadoop.io.Text;  
  185. import org.apache.hadoop.mrunit.mapreduce.MapDriver;  
  186. import org.junit.Before;  
  187. import org.junit.Test;  
  188.   
  189. import donation1.Donation.Djobmapper1;  
  190.   
  191. public class DonationTest {  
  192.     MapDriver<LongWritable, Text, Text, DoubleWritable> mapdriver;  
  193.   
  194.     @Before  
  195.     public void setup(){  
  196.         Djobmapper1 djm=new Djobmapper1();  
  197.         mapdriver=MapDriver.newMapDriver(djm);  
  198.     }  
  199.   
  200.     @Test  
  201.     public void testMapper() throws IOException{  
  202.         LongWritable inputKey = new LongWritable(0);  
  203.         Text inputValue=new Text("\"b1e82d0b63b949927b205441c543f249\",\"8a61c8ab4d91632dbf608ae6b1a832f3\",\"90b8c62c2e07a03d2cae3a0a52f18687\",\"\",\"NEWYORK\",\"NY\",\"100\",\"f\",\"2007-12-21 18:55:13.722\",\"85.00\",\"15.00\",\"100.00\",\"100_and_up\",\"t\",\"no_cash_received\",\"f\",\"t\",\"f\",\"f\",\"f\",\"f\",\"t\",\"\"");  
  204.         mapdriver.withInput(inputKey, inputValue);  
  205.         Text outputKey = new Text("NEWYORK");  
  206.         mapdriver.withOutput(outputKey, new DoubleWritable(0));  
  207.         mapdriver.runTest();  
  208.     }  
  209.   
  210. }</span></span></span>  

阅读更多
个人分类: 技术-大数据
上一篇MapReduce聚合
下一篇Mapreduce中Combiner的使用及误区
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭