本文為您介紹如何評估分區剪裁合理性。

背景信息

MaxCompute分區表是指在創建表時指定分區空間,即指定表內的幾個字段作為分區列。使用數據時,如果指定了需要訪問的分區名稱,則只會讀取相應的分區,避免全表掃描,提高處理效率,降低費用。

分區剪裁是指對分區列指定過濾條件,使得SQL執行時只用讀取表分區的部分數據,避免全表掃描引起的數據錯誤及資源浪費。但是分區失效的情況會經常發生。

本文將從以下兩方面介紹分區剪裁:
  • 判斷分區剪裁是否生效。
  • 分區剪裁失效的場景分析。

判斷分區剪裁是否生效

通過EXPLAIN命令查看SQL執行計劃,用于判斷SQL中的分區剪裁是否生效。
  • 分區剪裁未生效。
    explain
    select seller_id
    from xxxxx_trd_slr_ord_1d
    where ds=rand();

    從執行計劃中可見,SQL讀取了表的1344個分區,即該表的所有分區。

  • 分區剪裁生效
    explain
    select seller_id
    from xxxxx_trd_slr_ord_1d
    where ds='20150801';
    分區剪裁

    從執行計劃中可見,SQL只讀取了表的20150801分區。

分區剪裁失效的場景分析

  • 自定義函數導致分區剪裁失效
    當分區剪裁的條件中使用了用戶自定義函數(或者部分內建函數)時,分區剪裁失效。所以,對于分區值的限定,如果使用了非常規函數,建議您使用Explain命令查看執行計劃,確定分區剪裁是否生效。
    explain
    select ...
    from xxxxx_base2_brd_ind_cw
    where ds = concat(SPLIT_PART(bi_week_dim(' ${bdp.system.bizdate}'), ',', 1), SPLIT_PART(bi_week_dim(' ${bdp.system.bizdate}'), ',', 2))
    說明 UDF已支持分區裁剪,詳情請參見WHERE子句過濾(where_condition)文中的說明。
  • 使用JOIN時分區剪裁失效
    在SQL語句中使用JOIN進行關聯時:
    • 如果分區剪裁條件放在WHERE子句中,則分區剪裁會生效。
    • 如果分區剪裁條件放在ON子句中,從表的分區剪裁會生效,主表則不會生效。
    下面針對三種JOIN具體說明:
    • LEFT OUTER JOIN
      • 分區剪裁條件均放在ON子句中
        set odps.sql.allow.fullscan=true;
        explain
        select a.seller_id
            ,a.pay_ord_pbt_1d_001
        from xxxxx_trd_slr_ord_1d a
        left outer join
             xxxxx_seller b
        on a.seller_id=b.user_id
        and a.ds='20150801'
        and b.ds='20150801';
        **

        由上圖可見,左表進行了全表掃描,只有右表的分區裁剪有效果。

      • 分區剪裁條件均放在WHERE子句中
        set odps.sql.allow.fullscan=true;
        explain
        select a.seller_id
            ,a.pay_ord_pbt_1d_001
        from xxxxx_trd_slr_ord_1d a
        left outer join
            xxxxx_seller b
        on a.seller_id=b.user_id
        where a.ds='20150801'
        and b.ds='20150801';
        &&

        由上圖可見,兩張表的分區裁剪都有效果。

    • RIGHT OUTER JOIN

      與LEFT OUTER JOIN類似,如果分區剪裁條件放在ON子句中則只有RIGHT OUTER JOIN的左表生效。如果分區剪裁條件放在WHERE中,則兩張表都會生效。

    • FULL OUTER JOIN

      分區剪裁條件只有都放在WHERE子句中才會生效,放在ON子句中都不會生效。

注意事項

  • 分區剪裁如果失效影響較大,且不容易發現。因此,建議在代碼提交時關注分區剪裁失效問題。
  • 自定義函數中使用分區剪裁時,需要修改類或者在SQL語句前設置set odps.sql.udf.ppr.deterministic = true;。詳情請參見WHERE子句過濾(where_condition)