上一篇博客主要讲解了Pig的安装和一个试手的例子,下面说一下Pig的数据模型。 java
Pig的数据模型基本分为2大类,基本类型,和复杂类型。基本类型只能包含一个简单的数值,复杂类型能够包含其余全部类型。 程序员
基本类型,和其余大多数主流语言提供的简单类型同样,Pig也提供int, long, float, double,chararray(Sring),bytearray(字节类型) shell
Pig是用Java开发的,所以Java程序员应该能想象的到,上面的基本类型都是java.lang包中对应类型的实现的。 oop
须要注意的是,Pig的基本类型中没有Boolean值,可是在Pig的运行期倒是有Boolean值的,由于关系Filter须要一个Boolean关系为true时数据才能流过去。这点上须要注意。 spa
复杂类型包括Map, Tuple和Bag code
Map至关于Java的Map<String, Object>类型的。Key必须是一个chararray,而值能够是任何基本和复杂类型。表示为[key#value] 排序
Tuple能够理解为Java中的List,其实若是懂得Python,它更像Python中的Tuple[元组],表示为:(1, “abc”, 1.5)等 内存
Bag的数据类型按个人理解为Java的Set<Tuple>,它内部的数据是无序的。表示为:{(1, “abc”, 1.5),(2, “bcd”, 2.0)...} 开发
紧接着上一篇统计单词的例子,下面我作一些改写。一步一步的讲解Pig的运行数据状态。 rem
统计单词的第一步就是要把文本文件读入,而后分词。
words = load 'nie.txt' using PigStorage(' ') as (line);加载数据统一用load, 使用了PigStorage加载文件,Pig Storage默认是使用Tab分割文件中的内容的,由于个人例子是一片英文文章,所以只须要用空格作为分隔符就好 了。as (line)是在为数据指定模式,全部的数据加载进Pig都是Tuple类型的,所以使用(line),或者(line:chararray)。Tuple也能够指定多个值的,如(line:chararray,num1:int, num2:double),多个值的Tuple必需要数据要能转换成这样的,不然就会出错,或者加载了其余不对应的值也是空值,这样也没有意义。
Pig Latin脚本的任何地方均可以输出结果查看,咱们先看一下words的结果。
dump words;输出的结果:
(extravagant,) (without) (imagine) (in) (that) (unfathomable) (BECAUSE) (self-tyranny--Nature)我截取了一段结果,能够看到他们的数据都是Tuple,里边只有一个值。
所以若是为了统计词频,下一步应该是用Mapreduce的Map把相同的词汇集到一块儿,而后统计。下面的这句代码就很轻松的实现。
grpd = group words by line;紧接着,咱们输出grpd(dump grpd;)的结果查看。
(different,{(different),(different)}) (extremely,{(extremely)}) (mistaken,,{(mistaken,)}) (naturally,{(naturally)}) (ourselves,{(ourselves),(ourselves)}) (permitted,{(permitted)}) (something,{(something),(something)})熟悉MapReduce应该很清楚了,他把相同的词合并到了一块儿,组成了一个Tuple(word, {word, word})的数据格式。Reduce再把 {word, word }遍历一边得出一个count就实现了统计词频的效果了。
完整的程序:
words = load 'nie.txt' using PigStorage(' ') as (line); --以空格做为分隔符把内容分词读入 grpd = group words by line; --以每一个单词聚类,真实的是一个MapReduce的Map阶段 cntd = foreach grpd generate group, COUNT(words); -- 这里既上一步Map完成紧接着Reduce阶段进行统计 dump grpd; --直接在终端打印结果便于查看上面的程序正常运行下来应该能统计出词了该词出现的次数,文本很长的状况下着实没有什么意思,通常都会看前面高频的一些词汇,所以还应该作个Order By,而后取出前面的数据。幸亏Pig是支持的。
cous = order cntd by $1 desc; limitresult = limit cous 50; dump limitresult;
接着上面的dump前,继续排序,而后截取前面50条结果。
应该能看到,程序中使用了一个$1的的变量,由于foreach总会建立一个Tuple,而在COUNT()没有特别的指出别名,所以应该是匿名的,匿名的变量能够用$取出值,下标老是从0开始。Pig Latin是能够用as 强调别名的,这和SQL的AS是同样的。
运行该程序用的时间明显长了不少。运行结果如:
(the,32) (and,29) (of,21) (that,12) (in,12) (to,11) (is,10) (it,9) (a,9) (as,7) (for,6) (you,5) (will,4) (The,4) (value,3) (which,3)如今的结果明显有意义了不少。我在第一次运行这个程序的时候,还抛出了OutofMemory的异常,所以还更改了Pig的配置文件。PigHome/conf/pig.properties.在后边增长这样的配置:
pig.cachedbag.memusage=0 io.sort.mb=40 io.sort.record.percent=0.1Pig排序时须要很大的内存,经过参数能够把部分数据临时序列化到硬盘,具体的意义能够上Google搜。
之前玩Hadoop的朋友,是否是以为Pig能简化一些Mapreduce的开发呢?