背景と目的
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 句では失敗します。
影響と考慮事項
-
パーティションプルーニングの失敗は重大な結果をもたらしますが、ユーザーにはほどんどわかりません。 したがって、コードを送信するときに、失敗したパーティションプルーニングがあるかどうかを確認することを推奨します。
-
パーティションプルーニングにカスタム関数を使用できない問題を解決するには、さらに取り組みが必要です。