Pig基礎

jopen 10年前發布 | 13K 次閱讀 Pig 分布式/云計算/大數據

Pig和數據庫的區別

上一節講到了Pig的分組(group)和篩選(filter),讓人感覺這種用法和數據庫的SQL差不多。實際上Pig和傳統的關系型數據庫以及SQL語言是有很明顯區別的。我們逐個講解。

1)  Pig Latin是面向數據流的編程方式,而SQL是一種描述型編程語言。我們以前學習SQL的時候經常聽到過這樣一句話:用SQL,你只需要告訴它你需要什么,具體怎么做交給SQL就行了。而Pig Latin是需要你一步一步根據數據流的處理方式來編程的,也就是說你要設計數據流的每一個步驟,有點類似SQL的查詢規劃器。

2)  傳統的關系數據庫(RDBMS)需要你預先定義表結構(模式),所有的數據處理都是基于這些有著嚴格格式的表數據。而Pig則不需要這樣,你可以在運行時動態定義模式。本質上來說,Pig可以處理任何格式的元組。一般情況下,Pig的數據來源是文件系統,比如HDFS,而RDBMS的數據是存儲在數據庫中的。(備注:關于元組的概念,基本和Python中的touple是差不多的)

3)  Pig支持比較復雜的,比如嵌套結構的數據處理。這種特殊的處理能力加上UDF(用戶自定義函數)使得Pig具有更好的可定制型。

4)  一些RDBMS特有的特性是Pig所沒有的,比如事務處理和索引。Pig和MapReduce一樣,是基于批量的流式寫操作。

 

Hive是介于Pig和RDBMS之間的一種數據處理方案,其處理語言HiveQL類似于SQL,這就使得熟悉SQL的人可以快速熟悉和使用Hive。和Pig一樣,Hive的存儲方式也是基于文件系統(HDFS)。我們會在單獨的章節來講解Hive。

Pig Latin語法結構

本節我們只簡要介紹Pig的常用語法結構及相關概念。

1)  ls命令

顯示目錄結構。比如以下命令將列出HDFS的目錄結構。

ls /

備注:

1)  要列出HDFS的目錄結構,請確保當前是以MapReduce模式運行

2)  一般情況下,命令需要以分號顯式結束。但一些交互式命令不需要以分號結束,比如ls。如果你不能確定是否需要分號,加上一個分號總歸不會錯,比如“ls /;”。

3)  需要以分號結束的語句,可以將一個語句分成多行書寫,這樣可讀性更好。(有點類似Python)

4)  單行注釋可用雙連字符(--);多行注釋用類似于C語言的/*  */。

5)  和其它語言一樣,Pig的保留關鍵字不能作為標示符。

6)  Pig的大小寫敏感沒有一致的規定。操作和命令是不區分大小寫的,比如load,group。而函數式區分大小寫的,比如MAX。

2)  Explain命令

考慮如下語句:

records = load ‘/home/user/input/temperature1.txt’;

valid_records= filter records by temperature!=999;

grouped_records= group valid_records by year;

dumpgroup_records;

Pig Latin解釋器看到第一條load語句時,會執行數據的讀取操作嗎?不會,因為后續還可能會對數據進行篩序或分組。解釋器會生成load語句的邏輯計劃,但是并不會執行讀取操作,自然也就不會執行檢查工作,所以即使load的這個文件不存在,此時也不會報錯。最后,當碰到dump語句時,邏輯計劃即被編譯成物理計劃,并最終執行數據的讀取和輸出操作。

Pig的物理計劃是有一系列MapReduce作業組成的。使用explain命令即可查看這些邏輯計劃和物理計劃。

有些語句不會生成邏輯計劃,比如用于診斷操作的describe,expain語句等,這些語句會被解釋器立即執行。

3)  Set命令

Setdebug on用于開啟調試日志

Setjob.name ‘job name’ 用于設置MapReduce作業的名稱。Pig提交的MapReduce作業,如果沒有特別指明的話,作業名稱由系統生成。如果你希望給你的Pig作業指定一個有意義的名稱,以便可以方便的通過Hadoop的Web UI查看的話,set job.name將會是一個非常好的命令。

4)  run和exec

這兩個命令都可以執行Pig腳本。區別是exec以批處理方式運行,這意味著所有該腳本文件中定義的標示符,當腳本執行完后在腳本調用窗口將不可訪問。而以run運行時,相當于將腳本文件中的內容手工在調用窗口輸入并執行,這就意味著腳本文件中所有的標示符,比如定義的關系在腳本執行完后仍然可訪問,同時在shell的命令歷史記錄中可以找到腳本中的語句。

5)  表達式

Pig有豐富的表達式類型,和其它編程語言基本相似,比如加減乘除。

6)  類型

Pig有四種數值類型,分別是int,long,float和double。其用法和java一致。

bytearray類似java的字節數組,用于表示二進制大對象。

chararry類似java的string字符串,用于存儲utf-16格式的數據。當然,也可以處理utf-8的數據。

Pig沒有boolean類型,你可以使用int等其他類型輕松實現。

Pig還有一些比較復雜的數據類型,比如元組(touple),包(bag)和映射(map)。這些復雜類型的數據,一般從文件加載或由一些關系操作而得來。

包(bag)和關系(relation)的概念大致相似,但是其處理方式是有區別的。

包是元組的無序集合,比如{(1,’value’),(‘v1’,v2)}。而關系則是有名字的包,這個名稱成為關系的別名。一般情況下,一個Pig語句會產生一個關系。

通過文字直接創建一個關系是非法的,比如:

A = {(1,2)} –非法

將一個關系的字段投影為一個新的關系也是非法的,比如:

B = a.$0 –非法

作為一個變通方案,你可以用以下語句實現該功能:

B = foreach A genereate $0

將來的Pig版本也許會統一包和關系的處理模式,以消除這種不一致。

7)  模式

Pig中的關系可以有對應的模式。在模式中可以定義關系里面的字段的名稱和類型。正如我們先前看到的語句:

records= load ‘/home/user/input/temperature1.txt’ as (year: chararray,temperature: int);

其中 as子句定義了關系records的字段名稱和類型。執行describe records命令后,你將看到以下輸出:

records: {year: chararray,temperature:int}

Pig擅長于處理純文本信息,在模式定義方面提供了更大的靈活性,包括數據類型的選擇。這和傳統的關系型數據庫是有本質區別的。(傳統的RDBMS必須要事先定義嚴格的表結構)

在定義模式的時候,不需要為每個字段都定義類型。如果缺省,則pig指定默認類型為字節數組bytearray。

你甚至可以選擇不定義模式。但是一旦你選擇了定義模式,則必須為每個字段指明名稱和類型,當然類型是可選的。這意味著以下語句是合法的:

records= load ‘/home/user/input/temperature1.txt’;

如果你需要引用沒有定義模式的關系中的字段,則只能通過索引引用,而不能通過字段名稱來引用,因為你根本就沒有定義字段名稱。

在查詢中定義模式是非常靈活的。但是當很多查詢基于相同的模式時,這種在查詢中定義模式的方法就不利于重用和維護了。此時可以自己寫加載函數來實現,稍后我們再講。同時,apache開源項目Hcatalog提供了相關功能,其基于Hive的metastore實現。Pig可以充分利用這個功能,具體請參閱相關文檔。(我不太熟悉這個)

一般情況下,我們不需要為每一個關系定義其模式。比如通過filter篩序而來的新的關系和待篩選的數據源具有相同的模式。但是有些操作產生的關系卻有可能具有不同的模式,比如union操作。具體后續再詳細介紹。

8)  驗證和空值

傳統的關系數據庫中,如果你嘗試寫入一個類型不符的數據到數據庫,比如將字符‘a’寫到一個類型定義為int的字段,則會報錯。Pig的處理于此不同,比如load語句在讀取數據時,碰到了一個字符‘a’,而此位置的數據在模式定義中定義為int,則pig會用空值(null)取代之,同時會輸出提示信息,但是不會終止語句執行。本質原因是,對于大數據集而言,有一定比例的損壞數據是一種常見情況。此時我們可以通過如下語句進行篩選:

corrupt_records= FILTER records BY temperature is not null;

或者用split語句:

Splitrecords into good_one if temperature is not null, bad_one is temperature isnull;

9)  函數

Pig的函數有4種類型:

l  計算函數(Evalfunction)     比如MAX。(請注意,函數名是區分大小寫的)

l  篩選函數(Filterfunction)   用于過濾掉不需要的數據,比如ISEMPTY函數。

l  加載函數(loadfunction)     用于從外部數據源(比如文件)加載數據到關系。

l  存儲函數(stroefunction)   用于將關系中的數據輸出到外部存儲。比如PigStorage函數。

詳細函數列表,請參與官方文檔。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!