天天看點

MaxCompute的分區配置和使用

建立表的時候,可以設定普通列和分區列。在絕大多數情況下,可以把普通列了解成資料檔案的資料,而分區列可以了解成檔案系統的目錄。是以表的存儲空間的占用,講的是普通列的空間占用。分區列雖然不直接存儲資料,但是如同檔案系統裡的目錄,可以起到友善資料管理,并在計算隻指定具體的分區的時候,隻查詢對應分區減少計算量的作用。

MaxCompute的分區配置和使用

從這裡可以看到分區表的建立方式。目前分區列隻支援string類型。bigint目前是還在測試中,并無法保證其計算準确性,暫時還不建議大家使用。

目前分區表的分區列的個數不能超過6級,也可以了解成底層存儲資料的目錄層數不能超過6層。

分區的作用主要有2部分。其一是能友善資料的管理。使用了分區後,一張表的資料被分到多個不同的分區裡。比如日志表如果我們根據日期(天)進行分區,那麼每個分區裡都是單獨一天的資料。如果有一天我們希望能歸檔曆史資料到某個地方,或者删除過舊的資料,就隻需要處理對應的分區即可。在這裡還需要提一下lifecycle設定生命周期的功能,可以設定資料的過期時間,機關為天。maxcompute 會根據每張表的lastdatamodifiedtime以及lifecycle的設定來判斷是否要回收此表。如果這張表是分區表,則根據各分區的lastdatamodifiedtime判斷該分區是否該被回收。是以假如設定了過期時間是100天,然後資料是每天同步到一個分區裡,曆史分區的資料寫入後不再修改追加(lastdatamodifiedtime不變),那麼100天之前的曆史資料會被自動删除,減少運維成本。

但是更加有意義的是,如果計算中使用方法得當,分區表參與計算的時候能隻從指定的分區裡讀取資料作為輸入,進而能減少計算量,縮短計算時間,還能減少費用。以下是一個典型的例子:ods_oplog表裡有我模拟的2天(20161113、20161114)的日志(一共5條),ds作為分區。假如我的這次計算隻需要20161113的資料,我們可以用sql:

MaxCompute的分區配置和使用

從這個sql的執行計劃和最後的結果來看,雖然表裡有2個分區,但是因為使用了where ds='20161113',是以查詢的時候隻用到了ds='20161113'一個分區的資料,剩下的資料沒有做為input參與計算。

目前還有一個問題,如果查詢隻根據二級分區進行過濾,因為沒有指定一級分區是以會掃描所有一級分區,也一樣可能會出現這個錯誤。

關于sql裡查詢條件怎麼使用到分區帶來的好處,前面的分區的例子其實已經提到了。隻是需要注意的是,目前分區列需要是string類型,是以sql裡要寫成ds='20161113'不要寫成ds=20161113以避免自動類型轉換後得到預期外的結果。

對于分區表,資料寫入的時候需要指定資料寫入的分區,用文檔裡的例子:

再對應到前面提到的檔案和目錄的說法,因為資料的目錄不存放具體的資料,隻需要指定資料具體寫到哪個目錄後,把普通列的資料select出來後寫入到表裡就可以了。

但是确實有一些場景,需要把查詢結果,根據某個字段的值,智能得寫入到對應的分區裡,那就需要用到動态分區,具體的文法可以參考

在java裡,分區的對應的就是com.aliyun.odps.partitionspec了。這個類有2個構造,除了無參構造,還有一個傳入字元串的。

這是一個實際使用,需要傳入partitionspec 的例子(使用sdk建立一個新的分區)