1. 程式人生 > >MaxCompute重裝上陣 第五彈 - SELECT TRANSFORM

MaxCompute重裝上陣 第五彈 - SELECT TRANSFORM

mark .sql a20 易用性 推薦 unix add 不支持 工作

摘要: MaxCompute(原ODPS)是阿裏雲自主研發的具有業界領先水平的分布式大數據處理平臺, 尤其在集團內部得到廣泛應用,支撐了多個BU的核心業務。 MaxCompute除了持續優化性能外,也致力於提升SQL語言的用戶體驗和表達能力,提高廣大ODPS開發者的生產力。

MaxCompute(原ODPS)是阿裏雲自主研發的具有業界領先水平的分布式大數據處理平臺, 尤其在集團內部得到廣泛應用,支撐了多個BU的核心業務。 MaxCompute除了持續優化性能外,也致力於提升SQL語言的用戶體驗和表達能力,提高廣大ODPS開發者的生產力。

MaxCompute基於ODPS2.0新一代的SQL引擎,顯著提升了SQL語言編譯過程的易用性與語言的表達能力。我們在此推出MaxCompute(ODPS2.0)重裝上陣系列文章

第一彈 - 善用MaxCompute編譯器的錯誤和警告
第二彈 - 新的基本數據類型與內建函數
第三彈 - 復雜類型
第四彈 - CTE,VALUES,SEMIJOIN

上次向您介紹了CTE,VALUES,SEMIJOIN,本篇向您介紹MaxCompute對其他腳本語言的支持 - SELECT TRANSFORM。

場景1
我的系統要遷移到MaxCompute平臺上,系統中原來有很多功能是使用腳本來完成的,包括python,shell,ruby等腳本。 要遷移到MaxCompute上,我需要把這些腳本全部都改造成UDF/UDAF/UDTF。改造過程不僅需要耗費時間人力,還需要做一遍又一遍的測試,從而保證改造成的udf和原來的腳本在邏輯上是等價的。我希望能有更簡單的遷移方式。

場景2
SQL比較擅長的是集合操作,而我需要做的事情要對一條數據做更多的精細的計算,現有的內置函數不能方便的實現我想要的功能,而UDF的框架不夠靈活,並且Java/Python我都不太熟悉。相比之下我更擅長寫腳本。我就希望能夠寫一個腳本,數據全都輸入到我的腳本裏來,我自己來做各種計算,然後把結果輸出。而MaxCompute平臺就負責幫我把數據做好切分,讓我的腳本能夠分布式執行,負責數據的輸入表和輸出表的管理,負責JOIN,UNION等關系操作就好了。

上述功能可以使用SELECT TRANSFORM來實現

SELECT TRANSFORM 介紹
此文中采用MaxCompute Studio作展示,首先,安裝MaxCompute Studio,導入測試MaxCompute項目,創建工程,建立一個新的MaxCompute腳本文件, 如下

技術分享圖片

提交作業可以看到執行計劃(全部展開後的視圖):

技術分享圖片

Select transform允許sql用戶指定在服務器上執行一句shell命令,將上遊數據各字段用tab分隔,每條記錄一行,逐行輸入shell命令的stdin,並從stdout讀取數據作為輸出,送到下遊。Shell命令的本質是調用Unix的一些utility,因此可以啟動其他的腳本解釋器。包括python,java,php,awk,ruby等。

該命令兼容Hive的Transform功能,可以參考Hive的文檔。一些需要註意的點如下:

  1. Using 子句指定的是要執行的命令,而非資源列表,這一點和大多數的MaxCompute SQL語法不一樣,這麽做是為了和hive的語法保持兼容。
  2. 輸入從stdin傳入,輸出從stdout傳出;
  3. 可以配置分隔符,默認使用 \t 分隔列,用換行分隔行;
  4. 可以自定義reader/writer,但用內置的reader/writer會快很多
  5. 使用自定義的資源(腳本文件,數據文件等),可以使用 set odps.sql.session.resources=foo.sh,bar.txt; 來指定。可以指定多個resource文件,用逗號隔開(因此不允許resource名字中包含逗號和分號)。此外我們還提供了resources子句,可以在using 子句後面指定 resources ‘foo.sh‘, ‘bar.txt‘ 來指定資源,兩種方式是等價的(參考“用odps跑測試”的例子);
  6. 資源文件會被下載到執行指定命令的工作目錄,可以使用文件接口打開./bar.txt文件。

目前odps select transform完全兼容了hive的語法、功能和行為,包括 input/output row format 以及 reader/writer。Hive上的腳本,大部分可以直接拿來運行,部分腳本只需要經過少許改動即可運行。另外我們很多功能都用比hive更高執行效率的語言 (C++) 重構,用以優化性能。

應用場景舉例
理論上select transform能實現的功能udtf都能實現,但是select transform比udtf要靈活得多。且select transform不僅支持java和python,還支持shell,perl等其它腳本和工具。 且編寫的過程要簡單,特別適合adhoc功能的實現。舉幾個例子:

  1. 無中生有造數據
    技術分享圖片
    或者使用python

技術分享圖片
上面的語句造出一份有50行的數據表,值是從1到50; 測試時候的數據就可以方便造出來了。功能看似簡單,但以前是odps的一個痛點,沒有方便的辦法造數據,就不方便測試以及初學者的學習和探索。當然這也可以通過udtf來實現,但是需要復雜的流程:進入ide->寫udtf->打包->add jar/python->create function->執行->drop function->drop resource。

  1. awk 用戶會很喜歡這個功能
    技術分享圖片
    上面的語句僅僅是把value原樣輸出,但是熟悉awk的用戶,從此過上了寫awk腳本不寫sql的日子
  2. 用odps跑測試
    技術分享圖片
    或者
    技術分享圖片
    這個例子是為了說明,很多java的utility可以直接拿來運行。java和python雖然有現成的udtf框架,但是用select transform編寫更簡單,並且不需要額外依賴,也沒有格式要求,甚至可以實現離線腳本拿來直接就用。
  3. 支持其他腳本語言

select transform (key, value) using "perl -e ‘while($input = <STDIN>){print $input;}‘" from src;
上面用的是perl。這其實不僅僅是語言支持的擴展,一些簡單的功能,awk, python, perl, shell 都支持直接在命令裏面寫腳本,不需要寫腳本文件,上傳資源等過程,開發過程更簡單。另外,由於目前我們計算集群上沒有php和ruby,所以這兩種腳本不支持。

  1. 可以串聯著用,使用 distribute by和 sort by對輸入數據做預處理
    技術分享圖片
    或者用map,reduce的關鍵字會讓邏輯顯得清楚一些
    技術分享圖片
    理論上OpenMR的模型都可以映射到上面的計算過程。註意,使用map,reduce,select transform這幾個語法其實語義是一樣的,用哪個關鍵字,哪種寫法,不影響直接過程和結果。

性能
性能上,SELECT TRANSFORM 與UDTF 各有千秋。經過多種場景對比測試,數據量較小時,大多數場景下select transform有優勢,而數據量大時UDTF有優勢。由於transform的開發更加簡便,所以select transform非常適合做adhoc的數據分析。

UDTF的優勢:
UDTF是有類型,而Transform的子進程基於stdin/stdout傳輸數據,所有數據都當做string處理,因此transform多了一步類型轉換;
Transform數據傳輸依賴於操作系統的管道,而目前管道的buffer僅有4KB,且不能設置, transform讀/寫 空/滿 的pipe會導致進程被掛起;
UDTF的常量參數可以不用傳輸,而Transform沒辦法利用這個優化。
SELECT TRANSFORM 的優勢:
子進程和父進程是兩個進程,而UDTF是單線程的,如果計算占比比較高,數據吞吐量比較小,可以利用服務器的多核特性
數據的傳輸通過更底層的系統調用來讀寫,效率比java高
SELECT TRANSFORM支持的某些工具,如awk,是natvie代碼實現的,和java相比理論上可能會有性能優勢。
小結
MaxCompute基於ODPS2.0的SQL引擎,提供了SELECT TRANSFORM功能,可以明顯簡化對腳本代碼的引用,與此同時,也提高了性能!我們推薦您盡量使用SELECT TRANSFORM。

標註
註一,USING 後面的字符串,在後臺是直接起的子進程來調起命令,沒有起shell,所以shell的某些語法,如輸入輸出重定向,管道等是不支持的。如果用戶需要可以以 shell 作為命令,真正的命令作為數據輸入,參考“無中生有造數據”的例子;
註二,JAVA 和 PYTHON 的實際路徑,可以從JAVA_HOME 和 PYTHON_HOME 環境變量中得到作業;

原文鏈接

本文為雲棲社區原創內容,未經允許不得轉載。

MaxCompute重裝上陣 第五彈 - SELECT TRANSFORM