背景と目的

MaxCompute のパーティションテーブルは テーブル作成時に指定されたパーティションスペースを指します。 これは、テーブル内の特定のフィールドをパーティション列として参照します。 データを使用するとき、アクセスするパーティションの名前を指定した場合は、対応するパーティションからのみデータを読み取ります。 これにより、テーブル全体をスキャンする必要がなくなり、処理効率の向上とコストの削減に役立ちます。

パーティションプルーニングとは、パーティション列のフィルタリング条件を指定して、 SQL 実行時にテーブル内のパーティションデータの一部のみを読み取るようにすることです。 これにより、フルテーブルスキャンに起因するデータエラーとリソースの浪費を防止します。 パーティションプルーニングは単純に見えますが、実際にはパーティションの障害が頻繁に発生します。 ここでは、よくある問題の解決方法を、例を使用して紹介します。

問題の例

次の図は、テストテーブル test_part_cut のパーティションを示しています。

次の SQL コードを実行します。


select count(*)
from test_part_cut
where ds= bi_week_dim('20150102');

--bi_week_dim is a user defined function. The return format is (year,sequential number of the week).
--If the date is normal, the system checks whether the date belongs to weeks of the input year when taking Thursday as the start day of a week. For example, if 20140101 is input, 2013,52 is returned because January 1, 2014 is Wednesday and considered as the last week of 2013.  If 20150101 is input ,  2015,1 is returned.
--If 20151231 is input, because December 31, 2015 is Thursday and is in the same week as January 1, 2016 ,  2016,1 is returned.

bi_week_dim(‘20150102’) の戻り値は 2015,1 で、test_part_cut テーブルのパーティション値と一致しません。 一般的に、前述の SQL 文は パーティションを 1 つも読み取らないと考えられますが、実際には、test_part_cut テーブルのすべてのパーティションを読み取ります。 次の図に、LogView を示します。

前の図では、SQL 文の実行時に test_part_cut テーブルのすべてのパーティションが読み取られます。

前述の例は、使いやすいとはいえ、パーティションプルーニングは頻繁に失敗します。 したがって、ここでは次の側面に着目します。

  • SQL 文のパーティションプルーニングが有効かどうかを検証します。

  • パーティションプルーニングの失敗を招く一般的なシナリオを理解します。

パーティションプルーニングが有効かどうかの検証

explain コマンドを実行し、SQL の実行計画を表示して、SQL 文の中のパーティションプルーニングが有効かどうかを確認します。

  • パーティションプルーニングの失敗の影響

    
    explain
    select seller_id
    from xxxxx_trd_slr_ord_1d
    where ds=rand();

    前の図の赤枠は、xxxxx_trd_slr_ord_1d テーブルの 1,344 個のパーティションすべてが読み取られたことを示します。

  • パーティションプルーニングの成功の影響

    
    explain
    select seller_id
    from xxxxx_trd_slr_ord_1d
    where ds='20150801';

    前の図の赤枠は、xxxxx_trd_slr_ord_1d テーブルの 20150801 パーティションのみが読み取られたことを示します。

失敗したパーティションプルーニングのシナリオについての分析

カスタム関数またはシステム関数の一部が使用されているときに、パーティションプルーニングが失敗することがあります。 また、結合に Join 句が使用されている場合、Where 句で失敗する可能性があります。 これら 2 つのシナリオを、次の例で説明します。

カスタム関数によるパーティションプルーニングの失敗

パーティションプルーニングの条件にカスタム関数が含まれている場合、パーティションプルーニングは失敗します。 ただし、一部のシステム関数もパーティションプルーニングが失敗する可能性があります。 したがって、パーティション値の制限を考慮して、 explain コマンドを実行して SQL 文の実行計画を表示し、通常と異なる関数が使用されたときにパーティションプルーニングが有効になっているかどうかを検証する必要があります。


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))

前述の SQL 文では、パーティションプルーニングで使用されているカスタム関数が、フルテーブルスキャンのトリガーになります。

Join 句によるパーティショプルーニングの失敗

SQL 文では、 結合に Join 句を使用するとき、パーティションプルーニングの条件が on 句にある場合、パーティションプルーニングが有効になります。 条件が Where 句にある場合は、パーティションプルーニングはプライマリテーブルに対して有効になり、外部テーブルには適用されません。 3 つの Join 句は 次のように説明されます。

  • Left Outer Join

    • on 句にあるすべてのパーティションプルーニングの条件

      
      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 句に挿入

      
      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';

      前の図に示されているように、2 つのテーブルに対してパーティションプルーニングが有効になります。

  • Right Outer Join

    Left Outer Join と同様に、on 句にパーティションプルーニングの条件がある場合は、Right Outer Join の左側のテーブルのみに対して条件が有効になります。 Where 句に条件がある場合、 条件は両方のテーブルに対して有効になります。

  • Full Outer Join

    パーティションプルーニングの条件は Wlere 句でのみ有効になり、on 句では失敗します。

影響と考慮事項

  • パーティションプルーニングの失敗は重大な結果をもたらしますが、ユーザーにはほどんどわかりません。 したがって、コードを送信するときに、失敗したパーティションプルーニングがあるかどうかを確認することを推奨します。

  • パーティションプルーニングにカスタム関数を使用できない問題を解決するには、さらに取り組みが必要です。