在安装Pig之前,Hadoop环境已经配置好了,因此这里直接从安装Pig开始。
1. 下载Pig安装包
Pig-0.9.2下载地址:http://mirror.bjtu.edu.cn/apache/pig/pig-0.9.2/
在以上地址选择pig-0.9.2.tar.gz文件,也就是linux系统的压缩文件,下载到路径:/home/hadoop/HadoopHome
2.解压Pig安装包
在命令行切换至下载目录:
$ cd /home/hadoop/HadoopHome
在命令行解压缩安装包:
$ tar -zxvf pig-0.9.2.tar.gz
3.设置环境变量
在命令行以root用户编辑配置文件:
$ sudo vi /etc/profile
在文件末尾添加如下内容:
export PIG_INSTALL=/home/hadoop/HadoopHome/pig-0.9.2
export PATH=$PATH:$PIG_INSTALL/bin
export PIG_HADOOP_VERSION=20
export PIG_CLASSPATH=$HADOOP_INSTALL/conf
其中:PATH允许你在命令行使用pig命令;PIG_HADOOP_VERSION是告诉pig所使用的hadoop版本;PIG_CLASSPATH用来指定Hadoop配置文件所在的目录,分布式执行Pig的时候用到。
保存后重新加载profile文件以使其生效:
$ source /etc/profile
4.测试Pig安装结果
在命令行查看Pig帮助:
$ pig –help
… USAGE: …
1.准备实验数据
复制/etc/passwd文件到Pig的本地工作目录:
$ cp /etc/passwd /home/hadoop/HadoopHome/PigHome/
2.以本地模式打开和关闭Pig控制台
在命令行切换到Pig的本地工作目录:
$ cd /home/hadoop/HadoopHome/PigHome/
说明:因为打开Pig的交互程序,也就是Grunt Shell之后,无法使用linux命令行的指令,而Grunt Shell默认的路径是命令行的当前路径,因此切换到本地工作目录可以省去输入文件的绝对路径。
打开Grunt Shell方法一:
$ pig –x local
... - Connecting to ...
grunt>
打开Grunt Shell方法二:
$ java -cp pig.jar org.apache.pig.Main -x local
关闭Grunt Shell:
grunt> quit
3.执行Pig Latin语句
解析passwd文件:
grunt> A = load 'passwd' using PigStorage(':');
grunt> B = foreach A generate $0 as id;
grunt> dump B;
… (root) …
说明:以上语句先将passwd文件的内容加载到变量A,变量B通过遍历A的数据,取A的第一列作为id得来,最后使用dump命令输出B到控制台。所有的语句都仅仅被解析,直到执行了dump或者store命令。dump命令将打印出这个变量的内容,store命令将变量内容保存到文件中。最后注意,每一条命令都需要以分号结束。
说明:Pig Lartin语句一般以如下形式组织
1)一条Load语句来从文件系统读取数据
2)一系列转换语句来处理数据
3)一条Dump语句来查看结果,或者一条Store语句来保存结果
查看A的结构:
grunt> describe A;
Schema for A unknown.
grunt> describe B;
B: {id: bytearray}
说明,因为没有定义A的结构,所以是未知;定义了B的id列而没有指定数据类型,默认是bytearray类型。
查看B的前四行:
grunt> lmt = limit B 4;
grunt> dump lmt;
...
(adm)
(bin)
(root)
(deamon)
Pig支持的数据类型如下:
简单数据类型 |
描述 |
实例 |
基本型 |
|
|
int |
带符号的32位整数 |
10 |
long |
带符号的64位整数 |
数据:10L 或 10l 展示:10L |
Float |
32位浮点数 |
数据:10.5F 或 10.5f 或 10.5e2f 或 10.5E2F 展示:10.5F 或 1050.0F |
double |
64位浮点数 |
数据:10.5 或 10.5e2 或 10.5E2 展示:10.5 或 1050.0 |
数组型 |
|
|
chararray |
UTF-8编码的字符串 |
hello world |
bytearray |
字符数组(blob) |
|
复合数据类型 |
|
|
tuple |
一组有序字段 |
(19,2) |
bag |
若干tuple的集合 |
{(19,2),(18,1)} |
map |
一组键值对 |
[open#apache] |
1.Pig的默认数据类型和自动转换
grunt> A = load 'data' as (f1, f2, f3);
grunt> describe A;
A: {f1: bytearray, f2: bytearray, f3: bytearray}
说明:如果不指定数据类型,默认按bytearray类型处理。
grunt> B = FOREACH A GENERATE f1 + 5;
…
grunt> describe B;
…
B: {int}
说明:在B中因为5是整数,所以f1被转换为整数类型,这里命令行会有类型转换警告。
grunt> C = FOREACH A generate f1 + f2;
…
grunt> describe C;
…
C: {double}
说明,因为f1和f2的类型都不清楚,因此转换为double类型。
2.tuple类型
在工作目录PigHome下准备测试数据文件data,内容如下:
(3,8,9) (4,5,6)
(1,4,7) (3,7,5)
(2,5,8) (9,5,8)
注意:括弧间是制表符,如果替换为空格,则无法解析出第二个tuple。
解析和输出data文件:
grunt> A = load 'data' as (t1:tuple(t1a:int, t1b:int,t1c:int),t2:tuple(t2a:int,t2b:int,t2c:int));
grunt> dump A;
…
(3,8,9),(4,5,6)
(1,4,7),(3,7,5)
(2,5,8),(9,5,8)
抽取和输出data的数据:
grunt> X = FOREACH A GENERATE t1.t1a,t2.$0;
grunt> DUMP X;
…
(3,4)
(1,3)
(2,9)
3.bag类型
说明:
1)一个bag可以拥有多个tuple;
2)一个bag内的tuple可以拥有不同数量的字段,如果Pig尝试获取不存在的字段,该字段将被null替代;
3)一个bag内的tuple可以拥有不同的数据类型。然而为了Pig高效的处理这些bag,bag内的tuple应该拥有相同的结构
修改data的内容如下:
(1,2,3)
(4,2,1)
(8,3,4)
(4,3,3)
定义A然后输出:
grunt> A = load 'data' as (f1:int, f2:int, f3;int);
grunt> dump A;
(1,2,3)
(4,2,1)
(8,3,4)
(4,3,3)
说明,这里A可以看做一个relation或者一个bag,并且是一个外bag。
grunt> X = GROUP A BY f1;
grunt> DUMP X;
…
(1,{(1,2,3)})
(4,{(4,2,1),(4,3,3)})
(8,{(8,3,4)})
说明,这里X是一个relation或者bag。X作为relation时,其tuple有两个字段,第一个整数字段,第二个bag字段,这个bag是内bag。
1.准备试验数据文件
在PigHome创建文档文件A,内容如下:
0,1,2
1,3,4
创建文档文件B,内容如下:
0,5,2
1,7,8
2.使用union函数
分别加载A和B,然后使用union函数合并:
grunt> a = load 'A' using PigStorage(',') as (a1:int, a2:int, a3:int);
grunt> b = load 'B' using PigStorage(',') as (b1:int, b2:int, b3:int);
grunt> c = union a, b;
grunt> dump c;
…
(0,5,2)
(1,7,8)
(0,1,2)
(1,3,4)
3.使用split函数
将c分割为d和e,其中d的第一列数据值为0,e的第一列的数据为1:
grunt> split c into d if $0 == 0, e if $0 == 1;
grunt> dump d;
…
(0,1,2)
(0,5,2)
grunt> dump e;
…
(1,3,4)
(1,7,8)
4.使用filter函数
选择c中第二列值大于3的数据:
grunt> f = filter c by $1 > 3;
grunt> dump f;
…
(0,5,2)
(1,7,8)
5.使用group函数
对c的数据按第三列的值进行分组:
grunt> g = group c by $2;
grunt> dump g;
…
(2,{(0,1,2),(0,5,2)})
(4,{(1,3,4)})
(8,{(1,7,8)})
聚合所有的元素:
grunt> h = group c all;
grunt> dump h;
…
(all,{(0,1,2),(1,3,4),(0,5,2),(1,7,8)})
6.使用count函数
查看h中元素个数:
grunt> i = foreach h generate COUNT($1);
grunt> dump i;
…
(4)
说明:此处COUNT要大写,否则会有编译错误。
7.使用join函数
按照第三列连接a和b:
grunt> j = join a by $2, b by $2;
grunt> dump j;
…
(0,1,2,0,5,2)
pig能够支持两种类型的UDF:eval和load/store,其中load/store的自定义函数主要是用来加载和保存特定的数据格式;eval自定义函数主要用来进行常规的数据转换。
Pig安装文件夹下包含了一个eval的UDF实例UPPER.java,位于/myudfs目录下,该函数将输入的字符串转换为大写。这里直接使用该实例进行实验。
1.编译jar文件
切换到/myudfs目录:
$ cd /home/hadoop/HadoopHome/pig-0.9.2/myudfs
编译UPPER.java文件,生成jar文件:
$ javac -cp ../pig.jar UPPER.java
$ cd ..
$ jar -cf myudfs.jar myudfs
将myudfs.jar文件移动到PigHome:
$ mv myudfs.jar ~/HadoopHome/PigHome
2.准备实验数据
在PigHome下新建文档文件student_data,内容如下:
student1,1,1
studetn2,2,2
student3,3,3
student4,4,4
3.注册和使用该UDF
注册UDF:
grunt> register myudfs.jar
使用UDF:
grunt> A = load 'student_data' using PigStorage(',') as (name:chararray, age:int,gpa:double);
grunt> B = FOREACH A GENERATE myudfs.UPPER(name);
grunt> dump B;
…
(STUDENT1)
(STUDETN2)
(STUDENT3)
(STUDENT4)
1.准备数据文件
准备如下文档文件A,内容如下:
0,1,2
1,3,4
复制以上文件到HDFS:
grunt> fs –copyFromLocal A A
或者:
grunt> fs –put A A
说明:copyFromLocal和put是一个效果,且用法一致。
查看文件是否复制成功:
grunt> ls
hdfs:// … A …
grunt> cat A
0,1,2
1,3,4
新建文档文件myscript.pig,内容如下:
/*
Pig脚本文件
*/
a = load ‘A’ using PigStorage(‘,’); -- 加载文件A的数据
b = foreach a generate $0 as id; -- 遍历a的第一列
dump b; -- 输出b的结果
交互模式执行myscript.pig脚本:
grunt> run myscript.pig
…
(0)
(1)
说明:通过run命令执行脚本,可以在脚本与Grunt Shell之间进行交互(交互模式)。脚本内可以访问外部在Grunt Shell定义的aliase;Grunt Shell也可访问在脚本内定义的aliase。脚本的所有命令在Shell执行记录中可见。
批处理模式执行myscript.pig脚本:
grunt> exec myscript.pig
…
(0)
(1)
说明:以exec命令执行脚本,不会在脚本与Grunt Shell之间存在交互(批处理模式)。脚本和Shell不能互相访问aliase。脚本命令在Shell的执行记录也不可见。
以上。
南邮福富实验室