MaxCompute重裝上陣 第五彈 - SELECT TRANSFORM

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

    個人系統要遷移到MaxCompute平臺上,系統中原來有不少功能是使用腳原本完成的,包括python,shell,ruby等腳本。 要遷移到MaxCompute上,我須要把這些腳本所有都改形成UDF/UDAF/UDTF。改造過程不只須要耗費時間人力,還須要作一遍又一遍的測試,從而保證改形成的udf和原來的腳本在邏輯上是等價的。我但願能有更簡單的遷移方式。

  • 場景2
    shell

    SQL比較擅長的是集合操做,而我須要作的事情要對一條數據作更多的精細的計算,現有的內置函數不能方便的實現我想要的功能,而UDF的框架不夠靈活,而且Java/Python我都不太熟悉。相比之下我更擅長寫腳本。我就但願可以寫一個腳本,數據全都輸入到個人腳本里來,我本身來作各類計算,而後把結果輸出。而MaxCompute平臺就負責幫我把數據作好切分,讓個人腳本可以分佈式執行,負責數據的輸入表和輸出表的管理,負責JOIN,UNION等關係操做就行了。

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

SELECT TRANSFORM 介紹

此文中採用MaxCompute Studio做展現,首先,
導入測試MaxCompute項目,建立工程
,創建一個新的MaxCompute腳本文件, 以下

5ac16247e0b846b2673b47b462c7d73ac95ecd49

提交做業能夠看到執行計劃(所有展開後的視圖):ruby

9cd7ea0d4e9b11150cbbb81cc9d257da5346338f

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的數據分析。

UDTF的優點:

  1. UDTF是有類型,而Transform的子進程基於stdin/stdout傳輸數據,全部數據都當作string處理,所以transform多了一步類型轉換;
  2. Transform數據傳輸依賴於操做系統的管道,而目前管道的buffer僅有4KB,且不能設置, transform讀/寫 空/滿 的pipe會致使進程被掛起;
  3. UDTF的常量參數能夠不用傳輸,而Transform沒辦法利用這個優化。

SELECT TRANSFORM 的優點:

  1. 子進程和父進程是兩個進程,而UDTF是單線程的,若是計算佔比比較高,數據吞吐量比較小,能夠利用服務器的多核特性
  2. 數據的傳輸經過更底層的系統調用來讀寫,效率比java高
  3. SELECT TRANSFORM支持的某些工具,如awk,是natvie代碼實現的,和java相比理論上可能會有性能優點。

小結

MaxCompute基於ODPS2.0的SQL引擎,提供了SELECT TRANSFORM功能,能夠明顯簡化對腳本代碼的引用,與此同時,也提升了性能!咱們推薦您儘可能使用SELECT TRANSFORM。

標註

  • 注一,USING 後面的字符串,在後臺是直接起的子進程來調起命令,沒有起shell,因此shell的某些語法,如輸入輸出重定向,管道等是不支持的。若是用戶須要能夠以 shell 做爲命令,真正的命令做爲數據輸入,參考「無中生有造數據」的例子;
  • 注二,JAVA 和 PYTHON 的實際路徑,能夠從JAVA_HOME 和 PYTHON_HOME 環境變量中獲得做業;


本文做者:阿里雲高級技術專家 秋鵬
相關文章
相關標籤/搜索