DataWorks は、MaxCompute 2.0 SQL エンジンをベースにしたスクリプトモードでの開発をサポートする MaxCompute Script ノードを提供します。このトピックでは、MaxCompute Script ノードの使用方法について説明します。
背景情報
MaxCompute SQL エンジンはスクリプトモードをサポートしており、複数の SQL ステートメントを単一のスクリプトにまとめ、1つのユニットとしてコンパイルおよび実行できます。これは、ネストされたサブクエリや複数のステップを必要とする操作など、複雑なクエリに役立ちます。スクリプト全体を一度に送信することで、統一された実行計画が生成され、ジョブは一度だけキューに入れられて実行されます。このアプローチにより、リソースがより効率的に使用されます。詳細については、「SQL スクリプトモード」をご参照ください。DataWorks では、MaxCompute Script ノードを使用して、スクリプトベースのタスクを作成およびスケジューリングできます。
利用シーン
スクリプトモードは、深くネストされたサブクエリを書き換えたり、複雑なロジックを複数のステートメントに分割したりするのに最適です。
たとえば、スクリプトモードでは、定数を変数に割り当て、SELECT * FROM variable 文を使用してそれをスカラーに変換し、他の列との計算に使用できます。定数は、単一行のテーブルに格納することもできます。次の例をご参照ください。変換構文については、「サブクエリ (SUBQUERY)」をご参照ください。
@a := SELECT 10; -- 定数 10 を @a に割り当てます。または、SELECT col1 FROM t1 のように、単一行テーブル t1 から値を割り当てます。
@b := SELECT key,VALUE+(SELECT * FROM @a) FROM t2 WHERE key >10000; -- テーブル t2 の value 列と @a の値を使用して新しい値を計算します。
SELECT * FROM @b;
準備完了時刻が大幅に異なるデータソース (たとえば、一方が 01:00 に、もう一方が 07:00 に準備完了する場合など) を結合するために、テーブル変数を持つ単一のスクリプトを使用することは避けてください。すべてのデータが利用可能になるまでジョブは開始されず、大幅な遅延が発生する可能性があります。
前提条件
-
MaxCompute 計算リソースが DataWorks ワークスペースに関連付けられていること。
-
必要なテーブルが MaxCompute で作成され、サンプルデータが入力されていること。詳細については、「テーブル作成文とサンプルデータ」をご参照ください。
構文
完全な MaxCompute スクリプトは、SET ステートメント > DDL ステートメント > DML ステートメント の順序に従います。各タイプには 0 個以上のステートメントを含めることができますが、それらを混在させることはできません。アットマーク (@) で始まるステートメントは、ステートメント間で結果を渡すための変数を宣言します。構文は次のとおりです:
--SET ステートメント
SET odps.sql.type.system.odps2=true;
[SET odps.stage.reducer.num=***;]
[...]
--DDL ステートメント
CREATE TABLE table1 xxx;
[CREATE TABLE table2 xxx;]
[...]
--DML ステートメント
@var1 := SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table3
[WHERE where_condition];
@var2 := SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table4
[WHERE where_condition];
@var3 := SELECT [ALL | DISTINCT] var1.select_expr, var2.select_expr, ...
FROM @var1 JOIN @var2 ON ...;
INSERT OVERWRITE|INTO TABLE [PARTITION (partcol1=val1, partcol2=val2 ...)]
SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM @var3;
[@var4 := SELECT [ALL | DISTINCT] var1.select_expr, var.select_expr, ... FROM @var1
UNION ALL | UNION
SELECT [ALL | DISTINCT] var1.select_expr, var.select_expr, ... FROM @var2;
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
AS
SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM var4;]制限事項
MaxCompute Script ノードには、次の制限が適用されます:
-
スクリプトモードは、SET ステートメント、DML ステートメント、および一部の DDL ステートメントをサポートします。
DESCやSHOWのように画面に結果を表示する DDL ステートメントはサポートされていません。 -
スクリプトには、スタンドアロンの
SELECT文など、画面に結果を表示するステートメントを最大 1 つしか含めることができません。それ以外の場合は、エラーが返されます。スクリプト内で画面表示用のSELECT文を実行しないことを推奨します。 -
スクリプトには、
CREATE TABLE AS文を最大 1 つしか含めることができず、それは最後のステートメントでなければなりません。テーブル作成文とINSERT文は別々に記述することを推奨します。 -
スクリプトモードでは、いずれかのステートメントが失敗すると、スクリプト内のすべてのステートメントが失敗します。
-
スクリプトモードでは、すべての入力データが準備完了になった後にのみ、データ処理のためのジョブが生成されます。
-
スクリプトモードでは、テーブルに書き込んだ後にそのテーブルを読み取ろうとすると、エラーが返されます。
誤った例:
INSERT OVERWRITE TABLE src2 SELECT * FROM src WHERE key > 0; @a := SELECT * FROM src2; SELECT * FROM @a;正しい例:
書き込み後の読み取りの問題を回避するには、次のように変更できます。
@a := SELECT * FROM src WHERE key > 0; INSERT OVERWRITE TABLE src2 SELECT * FROM @a; SELECT * FROM @a;
MaxCompute Script ノードの作成
ノードの作成方法については、「MaxCompute Script ノードの作成」をご参照ください。
MaxCompute Script ノードの開発
MaxCompute Script ノードの編集ページで、ビジネスニーズに応じて次のスクリプト例を選択して開発できます。
基本的なスクリプト開発
MaxCompute スクリプトモードでは、SQL のコンパイルプロセスは単純です。次の簡単な例は、MaxCompute Script ノードの使用方法を示しています。
CREATE TABLE IF NOT EXISTS dest(key string , VALUE bigint) ;
CREATE TABLE IF NOT EXISTS dest2(key string,VALUE bigint ) ;
@a := SELECT * FROM src WHERE VALUE >0;
@b := SELECT * FROM src2 WHERE key IS NOT NULL;
@c := SELECT * FROM src3 WHERE VALUE IS NOT NULL;
@d := SELECT a.key,b.value FROM @a LEFT OUTER JOIN @b ON a.key=b.key AND b.value>0;
@e := SELECT a.key,c.value FROM @a INNER JOIN @c ON a.key=c.key;
@f := SELECT * FROM @d UNION SELECT * FROM @e UNION SELECT * FROM @a;
INSERT OVERWRITE TABLE dest SELECT * FROM @f;
@g := SELECT e.key,c.value FROM @e JOIN @c ON e.key=c.key;
INSERT OVERWRITE TABLE dest2 SELECT * FROM @g;
高度なスクリプト開発
MaxCompute スクリプトモードは IF 文をサポートしており、プログラムが条件に基づいて実行ロジックを自動的に選択できます。MaxCompute の IF 構文は、条件のタイプによって BOOLEAN 式と BOOLEAN スカラーサブクエリに分類されます。
-
IF 条件が BOOLEAN 式の場合
このタイプの
IF ELSE文は、コンパイル時にどのブランチを実行するかを決定します。例:--データ処理 SET odps.sql.allow.fullscan=true; SET odps.optimizer.cbo.rule.filter.black=LM; @date := '${var}'; @row TABLE(key int,VALUE bigint); --変数 row を宣言します。その型は Table で、スキーマは string です。 IF ( cast(@date AS bigint) % 2 == 0 ) BEGIN @row := SELECT key,VALUE FROM src1; END ELSE BEGIN @row := SELECT key,VALUE FROM src2; END INSERT OVERWRITE TABLE dest1 PARTITION(p='${var}') SELECT key,VALUE FROM @row;説明このコードは var という名前の変数を定義します。スケジューリングパラメーター設定で var 変数に値を割り当てる必要があります。
-
IF 条件が BOOLEAN スカラーサブクエリの場合
このタイプの
IF ELSE文は、コンパイル時にどのブランチを実行するかを決定できません。代わりに、ランタイムに決定されます。そのため、複数のジョブを送信する必要があります。例:@i bigint; @t TABLE(id bigint, VALUE bigint); IF ((SELECT count(*) FROM src WHERE a = '5') > 1) BEGIN @i := 1; @t := SELECT @i, @i*2; END ELSE BEGIN @i := 2; @t := SELECT @i, @i*2; END SELECT id, VALUE FROM @t; -
埋め込み UDF 開発
また、SQL スクリプトに Java または Python コードを埋め込んで、MaxCompute スクリプトモードで埋め込み UDF を開発することもできます。詳細については、「埋め込み UDF」をご参照ください。
MaxCompute Script ノードのデバッグ
-
ノード編集ページの右側にある Run Configuration で関連するパラメーターを設定します。
パラメーター
説明
計算リソース
関連付けた MaxCompute 計算リソースを選択します。
計算クォータ
作成した計算クォータを選択して、計算ジョブに必要なコンピューティングリソース (CPU とメモリ) を提供します。
利用可能な計算クォータがない場合は、ドロップダウンリストの [計算クォータの作成] をクリックし、MaxCompute コンソールで計算クォータを作成します。
リソースグループ
計算リソースとの接続テストに合格したスケジューリングリソースグループを選択します。詳細については、「ネットワーク接続」をご参照ください。
-
ツールバーのパラメーターダイアログで作成した MaxCompute データソースを選択し、Run をクリックして MaxCompute Script タスクを実行します。
次のステップ
-
スケジュール設定の構成:プロジェクトディレクトリ内のノードを定期的にスケジューリングする場合は、ノードの右側にある Scheduling Settings で Scheduling Policy と関連するスケジューリングプロパティを設定します。
-
ノードのデプロイ:タスクを本番環境にデプロイする場合は、
アイコンをクリックしてデプロイプロセスを開始します。プロジェクトディレクトリ内のノードは、本番環境にデプロイされた後にのみ定期的にスケジューリングされます。
テーブル作成文とサンプルデータ
例:
--テーブルの作成
CREATE TABLE IF NOT EXISTS src(key string ,VALUE BIGINT);
INSERT INTO src VALUES ('1',11) ;
INSERT INTO src VALUES ('1',11) ;
CREATE TABLE IF NOT EXISTS src2(key string ,VALUE BIGINT);
INSERT INTO src2 VALUES ('1',22);
INSERT INTO src2 VALUES ('2',22);
CREATE TABLE IF NOT EXISTS src3(key string ,VALUE BIGINT);
INSERT INTO src3 VALUES ('1',33);
INSERT INTO src3 VALUES ('3',33);