原创不易,转载请务必注明,原创地址,谢谢配合!
http://qindongliang.iteye.com/
Pig系列的学习文档,但愿对你们有用,感谢关注散仙!
Apache Pig的前世此生
Apache Pig如何自定义UDF函数?
Apache Pig5行代码怎么实现Hadoop的WordCount?
Apache Pig入门学习文档(一)
Apache Pig学习笔记(二)
Apache Pig学习笔记以内置函数(三)
玩转大数据系列之Apache Pig如何与Apache Lucene集成(一)
玩转大数据系列之Apache Pig如何与Apache Solr集成(二)
玩转大数据系列之Apache Pig如何与MySQL集成(三)
玩转大数据系列之如何给Apache Pig自定义存储形式(四)
玩转大数据系列之Apache Pig如何经过自定义UDF查询数据库(五)
如何使用Pig集成分词器来统计新闻词频?
在Hadoop的生态系统中,若是咱们要离线的分析海量的数据,大多数人都会选择Apache Hive或Apache Pig,在国内整体来讲,Hive使用的人群占比比较高, 而Pig使用的人相对来讲,则少的多,这并非由于Pig不成熟,不稳定,而是由于Hive提供了类数据库SQL的查询语句,使得大多人上手Hive很是容易,相反而Pig则提供了类Linux shell的脚本语法,这使得大多数人不喜欢使用。
若是在编程界,统计一下会SQL和会shell,那我的数占的比重大,散仙以为,毫无疑问确定是SQL语句了。由于有至关一部分编程人员是不使用Linux的,而是微软的的一套从C#,到ASP.NET,SQL Server再到Windows的专用服务器 。
OK,扯远了,赶忙回来,使用shell的攻城师们,我以为都会爱上它的,由于在linux系统中,没有比shell更简洁易用了,若是再配上awk和sed更是如虎添翼了。
咱们都知道shell是支持函数调用的,这一点和JavaScript是很是相似的,经过定义函数咱们能够重复使用某个功能,而不用再次大量编码,其中,把变的东西,分离成参数,不变的东西定义成语句,这样以来,就可以下降编码的冗余和复杂性,试想一下,若是Java里,没有方法,那将会是多么难以想象的一件事。
Pig做为类shell的语言,也支持了函数的方式,封装某个功能,以便于咱们重用,这一点相比Hive来讲,是一个很好的优点。
下面先看下定义Pig函数(也叫宏命令)定义的语法:
DEFINE (macros) :
支持的参数:
alias pig的标量引用
×××(integer)
浮点型(float)
字符串(String)
下面看几个例子,让咱们迅速对它熟悉并掌握,先看下咱们的测试数据:
java
1,张三,男,23,中国 linux
2,张三,女,32,法国 shell
3,小花,男,20,英国 数据库
4,小红,男,16,中国 编程
5,小红,女,25,洛阳 服务器
6,李静,女,25,中国河南安阳 ide
7,王强,男,11,英国 函数
8,张飞,男,20,美国 oop
1,张三,男,23,中国 2,张三,女,32,法国 3,小花,男,20,英国 4,小红,男,16,中国 5,小红,女,25,洛阳 6,李静,女,25,中国河南安阳 7,王强,男,11,英国 8,张飞,男,20,美国
再看下pig脚本:
--定义pig函数1 支持分组统计数量
DEFINE group_and_count (A,group_key,number_reduces) RETURNS B {
d = group $A by $group_key parallel $number_reduces;
$B = foreach d generate group, COUNT($1);
};
--定义pig函数2 支持排序
--A 关系引用标量
--order_field 排序的字段
--order_type 排序方式 desc ? asc ?
--storedir 存储的HDFS路径
--空返回值
define my_order(A,order_field,order_type,storedir) returns void {
d = order $A by $order_field $order_type ;
store d into '$storedir' ;
};
--定义pig函数3,支持filter过滤,以及宏命令里面调用
--定义过滤操做
define myfilter (A,field,count) returns B{
b= filter $A by $field > $count ;
$B = group_and_count(b,'sex',1);
};
a = load '/tmp/dongliang/318/person' using PigStorage(',') AS (id:int,name:chararray,sex:chararray,age:int,address:chararray) ;
--------pig函数1测试-----------------
--定义按名字分组
--bb = group_and_count(a,name,1);
--定义按性别分组
--cc = group_and_count(a,sex,1);
--dump bb;
--dump cc;
-------pig函数2测试------------------
--按年龄降序
--my_order(a,age,'desc','/tmp/dongliang/318/z');
--dump a;
-------pig函数3测试------------------
--过滤年龄大于20的,并按性别,分组统计数量
r = myfilter(a,'age',20);
dump r;
--定义pig函数1 支持分组统计数量 DEFINE group_and_count (A,group_key,number_reduces) RETURNS B { d = group $A by $group_key parallel $number_reduces; $B = foreach d generate group, COUNT($1); }; --定义pig函数2 支持排序 --A 关系引用标量 --order_field 排序的字段 --order_type 排序方式 desc ? asc ? --storedir 存储的HDFS路径 --空返回值 define my_order(A,order_field,order_type,storedir) returns void { d = order $A by $order_field $order_type ; store d into '$storedir' ; }; --定义pig函数3,支持filter过滤,以及宏命令里面调用 --定义过滤操做 define myfilter (A,field,count) returns B{ b= filter $A by $field > $count ; $B = group_and_count(b,'sex',1); }; a = load '/tmp/dongliang/318/person' using PigStorage(',') AS (id:int,name:chararray,sex:chararray,age:int,address:chararray) ; --------pig函数1测试----------------- --定义按名字分组 --bb = group_and_count(a,name,1); --定义按性别分组 --cc = group_and_count(a,sex,1); --dump bb; --dump cc; -------pig函数2测试------------------ --按年龄降序 --my_order(a,age,'desc','/tmp/dongliang/318/z'); --dump a; -------pig函数3测试------------------ --过滤年龄大于20的,并按性别,分组统计数量 r = myfilter(a,'age',20); dump r;
在上面的脚本中,散仙定义了三个函数,
(1)分组统计数量
(2)自定义输出存储
(3)自定义过滤并结合(1)统计数量
经过这3个例子,让你们对pig函数有一个初步的认识,上面的函数和代码都在一个脚本中,这样看起来不太友好,并且重用性,尚未获得最大发挥,实际上函数和主体脚本是能够分离的,再用的时候,咱们只须要导入函数脚本,便可拥有全部的函数功能,这样一来,函数脚本被分离到主脚本外面,就大大增长了函数脚本的重用性,咱们也能够再其余脚本中引用,并且函数脚本中也能够再次引用其余的函数脚本,但前提是不可以,递归引用,这样Pig语法在执行时,是会报错的,下面看下分离后的脚本文件:
一:函数脚本文件
--定义pig函数1 支持分组统计数量
--A 关系引用标量
--group_key 分组字段
--使用reduce的个数
--返回最终的引用结果
DEFINE group_and_count (A,group_key,number_reduces) RETURNS B {
d = group $A by $group_key parallel $number_reduces;
$B = foreach d generate group, COUNT($1);
};
--定义pig函数2 支持排序
--A 关系引用标量
--order_field 排序的字段
--order_type 排序方式 desc ? asc ?
--storedir 存储的HDFS路径
--空返回值
define my_order(A,order_field,order_type,storedir) returns void {
d = order $A by $order_field $order_type ;
store d into '$storedir' ;
};
--定义pig函数3,支持filter过滤,以及宏命令里面调用
--A 关系引用标量
--field 过滤的字段
--count 阈值
--返回最终的引用结果
define myfilter (A,field,count) returns B{
b= filter $A by $field > $count ;
$B = group_and_count(b,'sex',1);
};
[search@dnode1 pigmacros]$
--定义pig函数1 支持分组统计数量 --A 关系引用标量 --group_key 分组字段 --使用reduce的个数 --返回最终的引用结果 DEFINE group_and_count (A,group_key,number_reduces) RETURNS B { d = group $A by $group_key parallel $number_reduces; $B = foreach d generate group, COUNT($1); }; --定义pig函数2 支持排序 --A 关系引用标量 --order_field 排序的字段 --order_type 排序方式 desc ? asc ? --storedir 存储的HDFS路径 --空返回值 define my_order(A,order_field,order_type,storedir) returns void { d = order $A by $order_field $order_type ; store d into '$storedir' ; }; --定义pig函数3,支持filter过滤,以及宏命令里面调用 --A 关系引用标量 --field 过滤的字段 --count 阈值 --返回最终的引用结果 define myfilter (A,field,count) returns B{ b= filter $A by $field > $count ; $B = group_and_count(b,'sex',1); }; [search@dnode1 pigmacros]$
二,主体脚本文件
--导入pig公用的函数库
import 'function.pig' ;
a = load '/tmp/dongliang/318/person' using PigStorage(',') AS (id:int,name:chararray,sex:chararray,age:int,address:chararray) ;
--------pig函数1测试-----------------
--定义按名字分组
--bb = group_and_count(a,name,1);
--定义按性别分组
--cc = group_and_count(a,sex,1);
--dump bb;
--dump cc;
-------pig函数2测试------------------
--按年龄降序
--my_order(a,age,'desc','/tmp/dongliang/318/z');
--dump a;
-------pig函数3测试------------------
--过滤年龄大于20的,并按性别,分组统计数量
r = myfilter(a,'age',20);
dump r;
--导入pig公用的函数库 import 'function.pig' ; a = load '/tmp/dongliang/318/person' using PigStorage(',') AS (id:int,name:chararray,sex:chararray,age:int,address:chararray) ; --------pig函数1测试----------------- --定义按名字分组 --bb = group_and_count(a,name,1); --定义按性别分组 --cc = group_and_count(a,sex,1); --dump bb; --dump cc; -------pig函数2测试------------------ --按年龄降序 --my_order(a,age,'desc','/tmp/dongliang/318/z'); --dump a; -------pig函数3测试------------------ --过滤年龄大于20的,并按性别,分组统计数量 r = myfilter(a,'age',20); dump r;
须要注意的是,导入的函数文件,须要用单引号引发来,这样咱们就完成了pig函数的重用,是否是很是相似shell的语法呢?有兴趣的同窗们,赶忙体验一把吧!