MaxCompute(原ODPS)是阿里雲自主研發的具備業界領先水平的分佈式大數據處理平臺, 尤爲在集團內部獲得普遍應用,支撐了多個BU的核心業務。 MaxCompute除了持續優化性能外,也致力於提高SQL語言的用戶體驗和表達能力,提升廣大ODPS開發者的生產力。php
MaxCompute基於ODPS2.0新一代的SQL引擎,顯著提高了SQL語言編譯過程的易用性與語言的表達能力。咱們在此推出MaxCompute(ODPS2.0)重裝上陣系列文章html
第一彈 - 善用MaxCompute編譯器的錯誤和警告
第二彈 - 新的基本數據類型與內建函數
第三彈 - 複雜類型
第四彈 - CTE,VALUES,SEMIJOINjava
上次向您介紹了CTE,VALUES,SEMIJOIN,本篇向您介紹MaxCompute對其餘腳本語言的支持 - SELECT TRANSFORM。python
場景1
sql
場景2
shell
上述功能可使用SELECT TRANSFORM來實現apache
提交做業能夠看到執行計劃(所有展開後的視圖):ruby
Select transform容許sql用戶指定在服務器上執行一句shell命令,將上游數據各字段用tab分隔,每條記錄一行,逐行輸入shell命令的stdin,並從stdout讀取數據做爲輸出,送到下游。Shell命令的本質是調用Unix的一些utility,所以能夠啓動其餘的腳本解釋器。包括python,java,php,awk,ruby等。bash
該命令兼容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. 無中生有造數據
select transform(script) using 'sh' as (data) from
(
select 'for i in `seq 1 50`; do echo $i; done' as script
) t;
複製代碼
或者使用python
select transform('for i in xrange(1, 51): print i;') using 'python' as (data);
複製代碼
上面的語句造出一份有50行的數據表,值是從1到50; 測試時候的數據就能夠方便造出來了。功能看似簡單,但之前是odps的一個痛點,沒有方便的辦法造數據,就不方便測試以及初學者的學習和探索。固然這也能夠經過udtf來實現,可是須要複雜的流程:進入ide->寫udtf->打包->add jar/python->create function->執行->drop function->drop resource。
2. awk 用戶會很喜歡這個功能
select transform(*) using "awk '//{print $2}'" as (data) from src;
複製代碼
上面的語句僅僅是把value原樣輸出,可是熟悉awk的用戶,今後過上了寫awk腳本不寫sql的日子
3. 用odps跑測試
select transform(key, value)
using 'java -cp a.jar org.junit.runner.JUnitCore MyTestClass'
resources 'a.jar'
from testdata;
複製代碼
或者
set odps.sql.session.resources=a.jar;
select transform(key, value)
using 'java -cp a.jar org.junit.runner.JUnitCore MyTestClass'
from testdata;
複製代碼
這個例子是爲了說明,不少java的utility能夠直接拿來運行。java和python雖然有現成的udtf框架,可是用select transform編寫更簡單,而且不須要額外依賴,也沒有格式要求,甚至能夠實現離線腳本拿來直接就用。
4. 支持其餘腳本語言
select transform (key, value) using "perl -e 'while($input = <STDIN>){print $input;}'" from src;
複製代碼
上面用的是perl。這其實不只僅是語言支持的擴展,一些簡單的功能,awk, python, perl, shell 都支持直接在命令裏面寫腳本,不須要寫腳本文件,上傳資源等過程,開發過程更簡單。另外,因爲目前咱們計算集羣上沒有php和ruby,因此這兩種腳本不支持。
5. 能夠串聯着用,使用 distribute by和 sort by對輸入數據作預處理
select transform(key, value) using 'cmd2' from
(
select transform(*) using 'cmd1' from
(
select * from data distribute by col2 sort by col1
) t distribute by key sort by value
) t2;
複製代碼
或者用map,reduce的關鍵字會讓邏輯顯得清楚一些
@a := select * from data distribute by col2 sort by col1;
@b := map * using 'cmd1' distribute by col1 sort by col2 from @a;
reduce * using 'cmd2' from @b;
複製代碼
理論上OpenMR的模型均可以映射到上面的計算過程。注意,使用map,reduce,select transform這幾個語法其實語義是同樣的,用哪一個關鍵字,哪一種寫法,不影響直接過程和結果。
性能上,SELECT TRANSFORM 與UDTF 各有千秋。通過多種場景對比測試,數據量較小時,大多數場景下select transform有優點,而數據量大時UDTF有優點。因爲transform的開發更加簡便,因此select transform很是適合作adhoc的數據分析。
MaxCompute基於ODPS2.0的SQL引擎,提供了SELECT TRANSFORM功能,能夠明顯簡化對腳本代碼的引用,與此同時,也提升了性能!咱們推薦您儘可能使用SELECT TRANSFORM。