本文内容来自Hadoop权威指南,个人阅读的时候顺带整理翻译而来,并加入了自己的理解以及实际运行的配置。涵盖了Pig的核心内容,非常值得细读。如果你想获得本文更好的阅读体验,请访问这里.
版本记录:
- 2016-07 初稿
1. 环境配置:
wget http://mirror.bit.edu.cn/apache/pig/pig-0.15.0/pig-0.15.0.tar.gz
tar zxvf pig-0.15.0.tar.gz
mv ./pig-0.15.0 /home
加入到PATH,/etc/profile加入:
export PIG_HOME=/home/pig-0.15.0
export PATH=$PATH:$PIG_HOME/bin
source或者点操作确保生效。
确保配置了HADOOP_HOME环境变量:
echo $HADOOP_HOME
在运行pig之前,还需要NameNode启动JobHistory Server:
mr-jobhistory-daemon.sh start historyserve
jps
运行Grunt:
pig
可以看到pig选择了MapReduce模式,这是默认的模式。
2. Pig完整实例
载入数据:
records = LOAD '/input/ncdc/micro-tab/sample.txt' AS (year:chararray , temperature:int , quality:int);
输出数据:
dump records;
此时会提交MapReduce作业,如果没有启动作业历史服务器,MapReduce虽然执行成功,但是会报错:
成功输出结果:
查看YARN管理界面:
详情:
返回的records是个Relation,类似于表。Pig使用元组来表示记录。查看records的结构:
grunt> describe records;
records: {
year: chararray,temperature: int,quality: int}
grunt>
接着我们过滤掉脏数据:
filtered_records = FILTER records BY temperatur != 9999 and quality in ( 0 ,1,4,5,9);
dump filterd_records;
一样会触发MapReduce操作,输出结构到控制台。
接着进行分组:
grouped_records = GROUP filtered_records BY year;
DUMP grouped_records;
可以看到根据年份字段进行了分组,分组中是元组的列表,证实了我们前面说的Relation由元组构成。年份对应的{ },在Pig中成为bag,它是个无需的元组集合。
最后我们要从bag中找出温度最高的元组,继续之前我们看一下分组之后的结构:
grunt> describe grouped_records;
grouped_records: {
group: chararray,filtered_records: {(year: chararray,temperature: int,quality: int)}}
grunt>
Pig给分组后的key去了一个叫group
的别名,其值则为filtered_records,是个元素组成的bag,我们现在要在每一组group中找出温度最高的元组:
maxTemps = FOREACH grouped_records GENERATE group , MAX(filtered_records.temperature);
dump maxTemps;
我们完成了找出最高温度的代码:
records = LOAD ("hdfs://master:9000/input/ncdc/micro-tab/sample.txt") AS (chararray : year , int: temperature, int quality ) ;
filterd_records = FILTER records BY temperature != 9999 and quality in ( 0,1,4,5,9);
grouped_records = GROUP filtered_records BY year;
maxTemps = FOREACH grouped_records GENERATE group , MAX(filtered_records.temperature);
DUMP maxTemps;
我们现在使用ILLUSTRATE这个操作子来看一下整个数据处理流程。这个操作会生成一些合理的样本值,并按照整个处理流程展示:
ILLUSTRATE maxTemps;
3. Pig Latin
Pig Latin拥有自己特定的语法结构,不像Hive使用基于SQL的语言。
3.1 Pig Latin与SQL
这两种语言看起来很像,例如GROUP BY ,DESCRIBE等。但是他们之间还是有一些不同点:
1) Pig是一种数据流语言(data flow programming langage),而SQL是一种声明式的变成语言。Pig变成是一步一步对数据做处理和转换,而SQL只定义了需要什么样的数据。某种程度上,Pig脚本类似于SQL的查询计划,查询计划将声明式的结果转化为系统步骤。
2)SQL中,数据存储在表中,与特定的Schema绑定。Pig的数据结构则比较宽松,我们可以在处理的过程中定义Schema。例如文本文件中的一个值,在Pig处理过程中,我可以根据需要定义其类型为int,也可以定义为chararray。Pig的核心是在元组上进行操作,Pig程序的第一步通常是从文件系统(一般为HDFS)中读取数据,使用Pig内置的函数或者UDF转化为元组。文件的格式经常使用Tab分隔,所以Pig提供了LOAD用于加载这种格式的数据。
3) 另外,Pig支持复杂的嵌套的数据结构,这一点与SQL的单一层次(平面的,flatter)的表结构很不同。另外,Pig提供的自定义函数UDF以及流式操作(用于适配不同语言编写的UDF)使得Pig更加灵活和强大。
4)但是SQL及RDBMS提供的在线、低延时的查询,在Pig中是没有的,Pig没有事务和索引的概念。Pig也无法支持毫秒级别响应的随机读取,也不支持随机更新,所有的写入操作都是批量的流式(追加)写入,跟MapReduce一样。
Apache Hive则介于Pig和RDBMS之间。跟Pig一样,Hive使用HDFS作为存储。但是Hive提供的查询语言HiveQL是基于SQL,因此更容易上手。Hive也和关系型数据库一样要求数据必须存在表中,表的Schema由Hive管理,但是不同的是,Hive允许我们把一个Schema关联到已经存在的数据(位于HDFS),因此不需要加载的步骤(读取原始数据,转化为相应的结构)。Pig可以通过HCategory与Hive一起使用。
3.2 Pig程序结构:
一个Pig Latin程序包含一系列的语句(Statement),语句可以认为是一种操作或者命令。例如,GROUP BY是语句,列出Hadoop文件系统目录内容也是语句:
GROUP records BY year;
ls /
语句后面的分号有时候是必须的,有时候是可选的。一般情况下,用于交互式或者调试场景的可以不用分号,例如DESCRIBE命令。
如果命令必须使用分号,则可以让代码跨域多行。例如:
records = LOAD "path"
AS (year:chararray , temperature:int , quality:int);
3.3 注释
Pig有2种注释方式:
DUMP A; -- save to hdfs
/*
here is comment
*/
Pig的保留字包括操作子(LOAD,ILLUSTRATE),命令(cat,ls),表达式(matches , FLATTEN),函数(DIFF,MAX),这些不能在代码中作为标识符。
Pig的操作子和命令不区分大小写(使得写代码容错性更好),但是对于别名(aliases)和函数名,则是大小写敏感的。
3.4 语句
Pig程序运行时,每条依据依次被解析,如果有语法错误,解释器会停止并给出错误消息。解释器为每个操作创建一个逻辑的查询计划,加入到整个程序的查询计划中。需要注意的是,创建查询计划时,没有任何数据处理真正发生。Pig将整个程序作为一个整体解析,以便找出可以优化的地方,当像DUMP之类的语句时,才真正执行数据处理。这一点有点儿Spark中Transformation Lazy Evaluation的味道。下面的这个例子中:
A = LOAD "hdfs://master:9000/input/path";
B = FILTER A BY $1 == 'hadoop';
C = FILTER A BY $1 != 'hadoop';
STORE B INTO "output/b";
STORE C INTO "output/c";
上述代码中,B和C这两个Relation都是基于A的,因此Pig执行的时候,不会读取两次,而是把整个脚本作为一个MapReduce执行,输出两个文件。这个特性叫做多查询执行(multiquery execution)。旧版本的Pig中,两个STORE语句会分别启动MapReduce,因此加载两次输入文件。新版本中可以通过-M参数来关闭这个特性。
3.5 执行计划
Pig脚本的物理计划时一系列的MapReduce作业,在local模式下,在一个JVM中执行,在MapReduce模式下,在Hadoop集群上执行。可以通过EXPLAIN命令来查看逻辑计划和物理计划:
explain maxTemps;
这个语句同时还会战术MapReduce计划,MapReduce计划展示如何将物理计划中的操作(operator)归组为MapReduce作业。Pig中主要的操作如下:
载入和存储:
- LOAD:从文件系统或者其他存储载入数据到一个relation
- STORE:保存relation到文件系统或者其他存储
- DUMP(\d): 输出一个relation到控制台
过滤:
- FILTER: 从relation中移除不想要的行
- DISTINCT: 从relation中移除重复的行
- FOREACH … GENERATE:从relation中移除或者新增字段
- MAPREDUCE:使用relation作为输入运行一个MapReduce作业
- STREAM:使用外部程序(如Python)转换relation
- SAMPLE:从relation中采样
- ASSERT:确保relation满足特定条件,否则失败。
分组与关联:
- JOIN: 关联2个或者多个relation
- COGROUP: 对2个或多个relation的数据进行分组操作
- GROUP: 对一个单一的relation分组
- CROSS:对2个或多个relation求叉积
- CUBE:对relation中某些列的组合进行聚合
排序:
- ORDER:使用relation中的一