使用split_size優化的ODPS SQL的場景
首先有兩個大背景需要說明如下:
說明1:split_size,設定一個map的最大資料輸入量,機關M,預設256M。使用者可以通過控制這個變量,進而達到對map端輸入的控制。設定語句:set odps.sql.mapper.split.size=256。一般在調整這個設定時,往往是發現一個map instance處理的資料行數太多。
說明2:小檔案越多,需要instance資源也越多,MaxCompute對單個Instance可以處理的小檔案數限制為120個,如此造成浪費資源,影響整體的執行性能(檔案的大小小于塊Block 64M的檔案)。
場景一:單記錄資料存儲太少

原始Logview Detail:
可以發現Job隻調起一個Map Instance,供處理了156M的資料,但這些資料共有5千多萬的記錄(單記錄平均3個byte),花費了25分鐘。
此外,從TimeLine看可以發現,整個Job耗費43分鐘,map占用了超過60%的時間。故可對map進行優化。
優化手段:調小split_size為16M
優化之後的logview:
優化後,可以發現,Job調起了7個Map Instance,耗時4分鐘;某一個Map處理了27M的資料,6百萬記錄。(這裡可以看出set split_size隻是向Job提出申請,單不會嚴格生效,Job還是會根據現有的資源情況等來排程Instance)因為Map的變多,Join和Reduce的instance也有增加。整個Job的執行時間也下降到7分鐘。
場景二:用MapJoin實作笛卡爾積
原始logview:
可以發現,Job調起了4個Map,花費了3個小時沒有跑完;檢視詳細Log,某一個Map因為笛卡爾的緣故,生成的資料量暴漲。
綜合考慮,因為該語句使用Mapjoin生成笛卡爾積,再篩選符合條件的記錄,兩件事情都由map一次性完成,故對map進行優化。
政策調低split_size
優化後的logview:
![]
優化後,可以看到,Job排程了38個map,單一map的生成資料量下降了,整體map階段耗時也下降到37分鐘。
回頭追朔這個問題的根源,主要是因為使用mapjoin笛卡爾積的方式來實作udf條件關聯的join,導緻資料量暴漲。故使用這種方式來優化,看起來并不能從根本解決問題,故我們需要考慮更好的方式來實作類似邏輯。