MaxCompute(原ODPS)是阿裡雲自主研發的具有業界領先水準的分布式大資料處理平台, 尤其在集團内部得到廣泛應用,支撐了多個BU的核心業務。 MaxCompute除了持續優化性能外,也緻力于提升SQL語言的使用者體驗和表達能力,提高廣大ODPS開發者的生産力。
MaxCompute基于ODPS2.0新一代的SQL引擎,顯著提升了SQL語言編譯過程的易用性與語言的表達能力。我們在此推出MaxCompute(ODPS2.0)重裝上陣系列文章
第一彈 -
善用MaxCompute編譯器的錯誤和警告 第二彈 - 新的基本資料類型與内建函數 第三彈 - 複雜類型 第四彈 - CTE,VALUES,SEMIJOIN 第五彈 - SELECT TRANSFORM 第六彈 - User Defined Type 第七彈 - Grouping Set, Cube and Rollup 第八彈 - 動态類型函數 第八彈中提到了參數化視圖,本篇就向您介紹MaxCompute 腳本模式和參數化視圖。-
場景1
項目有個業務處理邏輯很複雜,需要讀多個表,某些表之間需要join,得出結果後再join,且要從不同的運算階段輸出多個表,即使用
CTE 也無法表達,隻好将此業務邏輯拆分為多個作業,按順序送出,如此一來使得作業又複雜性能也不好。 -
場景2
目前Project有個資料表需要分享給多個團隊使用,考慮安全性做成了視圖, 視圖是通過一個算法模式實作。其他團隊發現此算法挺好也想用,但是底層通路的資料表不一樣,一些模式識别的參數也不一樣,沒辦法隻好再做一個新的視圖提供。若後續發現原來的視圖有bug,那麼隻能一個個的修複。
MaxCompute 提供的腳本模式與參數化視圖,基本解決了上述場景中的問題。
腳本模式
此文中采用MaxCompute Studio作展示,首先,
安裝MaxCompute Studio,
導入測試MaxCompute項目,建立工程,建立一個新的MaxCompute腳本檔案, 如下

注意,要選取MaxCompute Studio的腳本模式。這樣編譯器就會将整個檔案作為一個整體編譯,而不是一個一個語句的編譯,送出的時候,也是整體送出。
觀察此腳本,可以看到其從多個表src, src1, src2讀取資料,中間可以做任意的filter, union, join等操作,最後輸出到多個表,dest和dest1中。多個語句以@開始的表變量連接配接。編譯後送出腳本運作,可以通過MaxCompute Studio的作業試圖察看執行計劃,如下:
右鍵點選圖中任意task,彈出菜單點選“expand all”,可以在一個視圖中看到執行計劃所有operator及其互相關系,如下:
可以看到雖然有多個語句,但是執行計劃是互相連通的一個DAG。這樣的執行計劃,用傳統的SQL語句,不管是CTE還是multi INSERT,都無法生成。一個執行計劃可以保證一次排隊,一次執行,充分利用了MaxCompute的資源。且書寫起來也更自然,隻需要按照業務邏輯,用類似于普通程式設計語言的方式書寫,不用分心考慮如何組織語句,比如使用CTE和MULTI INSERT等,來優化性能。
同時,MaxCompute的優化器,比起多個語句分别執行,在腳本模式下能夠看到更完整的執行計劃,也就可以有更多的優化機會,生成全局最優的實體執行計劃,提高性能。
腳本模式也支援SET語句和部分DDL語句。例如:
一個腳本的完整形式是先SET語句,然後DDL語句,最後DML語句。每個部分都可以有0到多個語句,但是不同類型的語句不能交錯。
需要注意的是,在腳本模式下,如果一個表先被寫,又被讀,會報告錯誤,避免混淆。例如以下語句會報錯
insert overwrite table src2 select * from src where key > 0;
@a := select * from src2;
select * from @a;
建議您在書寫的時候,避免先寫後讀,例如以上腳本可以修改為:
@a := select * from src where key > 0;
insert overwrite table src2 select * from @a;
select * from @a;
這樣就可以列印出會寫入src2中的内容了。
腳本模式下目前還有一些限制
- 一個腳本,目前最多支援一個屏顯語句,否則會報告錯誤。不建議在腳本中執行螢幕顯示的SELECT語句。
- 一個腳本,目前最多支援一個CREATE TABLE AS語句并且必須是最後一句。我們推薦您将建表語句與INSERT語句分開寫,如上面提到的DDL和DML混合的腳本。
通過MaxCompute CMD使用腳本模式
腳本模式是一種新的模式,如果使用MaxCompute CMD來送出腳本,需要使用0.27以上的版本。建議您
下載下傳安裝最新版本。安裝後,請使用新的 -s 參數來送出 。
如編輯腳本模式的源碼myscript.sql檔案,調用odpscmd指令執行如下。
odpscmd -s myscript.mysql;
說明 -s 為odpscmd的指令行選項,類似于-f、-e,而非互動環境中的指令。odpscmd的互動環境中暫不支援腳本模式與表變量。
如果希望傳遞一些setting,但是又不想寫在腳本裡面,可以按照如下的方,使用-e參數來單獨傳遞setting
odpscmd -e 'set odps.sql.setting1=a;odps.sql.setting2=b='-s myscript.sql
通過DataWorks使用腳本模式
在DataWorks中可以建立腳本模式的節點ODPS Script,如下圖所示。
在此節點中進行腳本模式編輯,編輯完成後單擊工具欄的運作按鈕,送出腳本到MaxCompute執行。從輸出資訊的Logview URL中可以檢視執行計劃圖和結果。
什麼時候不應将多個小SQL語句組合為一個大模式腳本SQL
腳本模式能夠支援複雜的邏輯,一個腳本可以有很多行,編譯為一個執行計劃,這樣很容易将原來在多個SQL節點中的語句通過table variable銜接起來,拼裝為一個大的腳本模式SQL。但是,并不是所有場景都适合。
例如,如果上遊資料來源于兩個每日更新的表,一個淩晨1點資料準備好,一個淩晨7點準備好,原來一個SQL節點1點的時候處理第一個資料,結果存為一個中間表。另一個SQL節點在7點的時候将此中間表和第二個資料源作進一步運算得到結果資料。這種場景就不适合将兩個節點中的SQL組合為一個大腳本。因為一個SQL節點本來可以更早的做好資料預處理,如果合成一個大腳本,就隻能在7點所有資料都到達後生成一個作業,本來可以預處理的也要在大作業中完成,反而造成全鍊路E2E時間更長,出錯的機率也更高。
腳本模式更适合用來改寫本來要用層層嵌套子查詢的單個語句,或者因為腳本複雜性而不得不拆成多個語句的腳本。
參數化的視圖 (VIEW)
MaxCompute傳統的VIEW,可以封裝一段SQL腳本,底層的邏輯可以很複雜,比如通路多個表,做複雜的運算,但是調用者可以像讀普通表一樣調用VIEW,不關心底層實作。這樣的VIEW實作了一定的封裝與重用,使用非常廣泛。
但是傳統的VIEW也有一個限制,就是不能接受任何調用者傳遞的參數。例如某個VIEW讀取一個底層表,希望調用者可以提供一個表對底層資料進行過濾,或者傳遞任何其他參數,這些需求傳統VIEW都不支援。如此便限制了傳統VIEW在代碼重用方面的能力,而開發中仍經常需要多次複制類似的代碼。
MaxCompute支援帶參數的VIEW,可以傳入任意表或者其他變量,定制VIEW的行為。
首先在MaxCompute建立一個新的MaxCompute腳本檔案, 如下:
可以看到,pv有兩個參數,一個是表參數,一個是string參數,參數可以是任意的表或者基本類型。建立另一個腳本調用此VIEW,如下:
可以看到pv1可以用不同的參數調用,表參數可以是個實體表,view,表變量或者CTE中的表别名,普通參數可以是變量或者常量。
點選此腳本的graph頁 (上圖中最下邊的紅框),可以看到此腳本對應的執行計劃:
可以看到,不管調用多少次,用什麼樣的參數,MaxCompute編譯器都會将整個腳本編譯為一個執行計劃。
實際上,參數化VIEW不一定是一個SQL語句,也可以像腳本一樣,包含多個語句。例如:
其中BEGIN到END;之間的語句,就是這個VIEW的腳本。注意其中最後一句,@pv2 := ...,這個語句相當于是其他語言中的RETURN語句,方式為向一個與VIEW同名的隐含的表變量指派。
在VIEW參數比對的時候,實參和形參比對的規則和普通語言一樣。如果可以隐式轉換,就可以比對,例如bigint的值可以比對類型為double的參數。表變量相對複雜一些,但是規則也很簡單,如果一個表的Schema,能夠用來插入到另一個表中,那也可以用來比對同樣表Schema的表類型參數。
對于傳回的類型,有的時候希望明确聲明,例如為了可讀性。可以明确地聲明傳回類型,例如:
其中的RETURNS @ret TABLE (x string, y string), 定義了:
- 傳回類型為TABLE (x string, y string)。也就是傳回給調用者的類型,注意可以在此定制表的Schema
- 傳回參數為@ret,在VIEW的腳本中對其指派,就相當于傳回。
實際上,對于沒有BEGIN/END和沒有傳回變量的VIEW,都可以認為是這種形式的簡化形式。
在參數化VIEW的時候,對于腳本有一些其他限制。
- 腳本中隻能由DML語句,并且不能有INSERT與CREATE TABLE AS語句。
- 腳本中不能有螢幕顯示語句。
最後,MaxCompute提供了新的腳本模式與參數化視圖,可以明顯提高開發者的程式設計效率,提高代碼的可重用性,與此同時,也提高了性能!我們推薦您盡量使用腳本模式和參數化視圖。