DataWorksは、MaxCompute V2.0 SQLエンジンが提供するコードエディターでMaxComputeスクリプトタスクを開発するためのODPSスクリプトノードを提供します。このトピックでは、ODPSスクリプトノードを使用してMaxComputeスクリプトタスクを開発する方法について説明します。
前提条件
ODPSスクリプトノードが作成されていること。詳細については、「ODPSノードの作成と管理」をご参照ください。
背景情報
MaxComputeのSQLエンジンはスクリプトモードをサポートしています。スクリプトモードでは、複数のSQL文を含むSQLスクリプトファイルが全体としてコンパイルされます。SQLスクリプトファイル内の各文を個別にコンパイルする必要はありません。スクリプトモードは、ネストされたサブクエリを持つ単一の文を書き直す必要がある場合、または複雑なスクリプトを複数の文に分割する必要がある場合に使用されます。SQLスクリプトファイルがコンパイルされると、MaxComputeに送信され、実行プランが生成されます。このように、SQLスクリプトファイル内の文は1つのキューでスケジュールされ、一度に実行されます。これにより、MaxComputeのリソースを最大限に活用できます。詳細については、「スクリプトモードのSQL」をご参照ください。DataWorksでは、ODPSスクリプトノードを作成して、スクリプトモードでMaxComputeスクリプトタスクのコードを開発し、MaxComputeスクリプトタスクを他のタスクと統合できます。
シナリオ
スクリプトモードは、以下のシナリオで使用できます。
ネストされたサブクエリを持つ単一の文を書き直す必要がある場合、または複雑なスクリプトを複数の文に分割する必要がある場合。
スクリプトモードはこのシナリオには適用できません。複数のデータソースのデータを追加する必要があり、異なるデータソース間でデータ準備に長い時間間隔が存在する場合。たとえば、あるデータソースのデータは01:00に準備完了し、別のデータソースのデータは07:00に準備完了します。この場合、テーブル変数はSQLスクリプトファイル内の複数の文をパッケージ化するには適していません。
変数に定数値を割り当て、
SELECT * FROM Variableステートメントを実行して、変数をスカラー値に変換する必要があります。スカラー値は、他の列と共に計算に使用されます。定数値は、1 行のみのテーブルに格納することもできます。次のステートメントは例を示しています。SELECT * FROM Variable ステートメントの構文の詳細については、「サブクエリ」をご参照ください。@a := SELECT 10; -- 定数 10 を @a に代入します。1 行のみのテーブル t1 に格納されている定数を @a に代入するために SELECT col1 FROM t1 を使用することもできます。 @b := SELECT key,value+(SELECT * FROM @a) FROM t2 WHERE key >10000; -- テーブル t2 の値と @a の値を使用して計算を行います。 SELECT * FROM @b;
構文
完全な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;]制限事項
ODPSスクリプトノードを使用する場合、以下の制限が課せられます。
ODPSスクリプトノードは、スクリプトモードでSET文、DML文、および一部のDDL文をサポートしています。
DESCやSHOWなど、結果を表示するDDL文はサポートされていません。
スクリプトには、SELECT文など、結果を表示する文を1つだけ記述できます。スクリプトに複数のそのような文を記述すると、エラーが発生します。スクリプトでは、結果を表示するSELECT文を使用しないことをお勧めします。
スクリプトには、
CREATE TABLE AS文を1つだけ記述でき、この文はスクリプトの最後の文である必要があります。CREATE TABLE文とINSERT文は、異なるセクションに記述して分離することをお勧めします。スクリプトモードでは、スクリプト内の1つの文が失敗すると、スクリプト全体が失敗します。
スクリプトモードでは、スクリプトのすべての入力データが準備された後にのみ、データを処理するためのジョブが生成されます。
スクリプトモードでは、テーブルにデータを書き込む文と、同じスクリプト内でテーブルからデータを読み取る文を指定すると、エラーが発生します。たとえば、次の文をスクリプトに記述すると、エラーが発生します。
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;
簡単なコード編集例
ODPSスクリプトノードを使用すると、一般的なプログラミング言語を使用するのと同じように、ビジネスロジックに基づいてSQL文を記述できます。SQL文をどのように構成するかを考慮する必要はありません。次の例では、ODPSスクリプトノードの使用方法について説明します。
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;この例では、src、src1、および src2 テーブルが使用されます。テーブルを作成する文:
-- テーブルを作成します。
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);高度なコード編集例
MaxComputeのスクリプトモードは、IF文をサポートしています。IF文を使用すると、特定の条件に基づいて実行ロジックを自動的に選択できます。MaxComputeは、条件タイプに基づいて、BOOLEANおよびBOOLEAN型スカラーサブクエリのIF構文をサポートしています。
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); -- 行変数を宣言します。行のタイプは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)の開発
MaxCompute スクリプトモードを使用して、Java または Python コードを SQL スクリプトに埋め込むことで、埋め込み UDF 開発を実装できます。 詳細については、コード埋め込み UDF をご参照ください。
次の手順
作成したノードを使用してタスクの開発を完了した後、以下の操作を実行できます。
スケジューリングプロパティの設定:ノードの定期的なスケジューリングのプロパティを設定できます。システムによってタスクが定期的にスケジュールおよび実行されるようにするには、再実行設定やスケジューリングの依存関係など、ノードの項目を設定する必要があります。詳細については、「スケジュール」をご参照ください。
ノードのデバッグ:ノードのコードをデバッグおよびテストして、コードロジックが期待どおりに動作するかどうかを確認できます。詳細については、「デバッグ手順」をご参照ください。
ノードのデプロイ:すべての開発操作が完了したら、ノードをデプロイできます。ノードがデプロイされると、システムはノードのスケジューリングプロパティに基づいてノードを定期的にスケジュールします。詳細については、「ノードのデプロイ」をご参照ください。