原創不易,轉載請務必註明,原創地址,謝謝配合!
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)
下面看幾個例子,讓我們迅速對它熟悉並掌握,先看下我們的測試數據:
1,張三,男,23,中國
2,張三,女,32,法國
3,小花,男,20,英國
4,小紅,男,16,中國
5,小紅,女,25,洛陽
6,李靜,女,25,中國河南安陽
7,王強,男,11,英國
8,張飛,男,20,美國
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的語法呢?有興趣的同學們,趕緊體驗一把吧!