U-SQL 開発者向けの Apache Spark コードについて
重要
Azure Data Lake Analytics は 2024 年 2 月 29 日に廃止されました。 詳細については、このお知らせを参照してください。
データ分析の場合、組織は Azure Synapse Analytics または Microsoft Fabric を使用できます。
このセクションでは、U-SQL スクリプトの Apache Spark への変換に関する概要を説明します。
- まず、2 つの言語の処理パラダイムを比較することから始めます
- 次の方法に関するヒントを提供します。
- U-SQL の行セット式を含むスクリプトを変換する
- .NET コード
- データ型
- カタログ オブジェクト
U-SQL および Spark 言語と処理パラダイムを理解する
Azure Data Lake Analytics の U-SQL スクリプトを Spark に移行する前に、これら 2 つのシステムの一般的な言語と処理の理念を理解しておくと役に立ちます。
U-SQL は、データフロー パラダイムを使用する SQL に似た宣言型クエリ言語であり、.NET で記述されたユーザーコード (たとえば C#)、Python、R を簡単に埋め込んだりスケールアウトしたりすることができます。ユーザー拡張機能を使用すると、単純式またはユーザー定義関数を実装できるだけでなく、カスタム演算子を実装するユーザー定義演算子を実装することで、ユーザーが行セットレベルの変換、抽出、および出力の書き込みを実行できるようになります。
Spark は、Scala、Java、Python、.NET などの複数の言語バインディングを提供するスケールアウト フレームワークです。主にこれらの言語のいずれかでコードを記述し、Resilient Distributed Datasets (RDD)、データフレーム、およびデータセットと呼ばれるデータの抽象化を作成し、その後 LINQ に似たドメイン固有言語 (DSL) を使用して変換します。 また、Spark は宣言サブ言語としてデータフレームとデータセットの抽象化で SparkSQL を提供します。 DSL には、変換とアクションの 2 つの操作カテゴリがあります。 データの抽象化に変換を適用しても変換は実行されませんが、代わりに、アクションにより送信される評価用の実行プランが作成されます (たとえば、一時テーブルやファイルに結果を書き込んだり、結果の印刷など)。
このため、U-SQL スクリプトを Spark プログラムに変換する場合、少なくともデータフレームの抽象化 (現在最も頻繁に使用されているデータ抽象化) を生成するために使用する言語と、DSL または SparkSQL のどちらを使用して宣言型データフロー変換を行うかどうかを決定する必要があります。 さらに複雑な一部のケースでは、U-SQL スクリプトを Azure Batch または Azure Functions で実装された一連の Spark とその他の手順に分割することが必要な場合があります。
さらに、Azure Data Lake Analytics では、各ジョブにリソースが割り当てられるサーバーレス ジョブ サービス環境で U-SQL が提供されますが、Azure Synapse Spark、Azure Databricks、Azure HDInsight では、クラスター サービスの形式またはいわゆる Spark プール テンプレートを使用して Spark が提供されます。 アプリケーションを変換する際には、クラスターまたはプールの作成、サイズ変更、スケーリング、および使用停止の影響について考慮する必要があります。
U-SQL スクリプトの変換
U-SQL スクリプトは、次の処理パターンに従います。
- データは、場所またはファイルセットを指定する
EXTRACT
ステートメント、組み込みまたはユーザー定義のエクストラクターおよび必要なスキーマを使用して非構造化ファイルから読み取られるか、U-SQL テーブル (マネージテーブルまたは外部テーブル) から読み取られます。 これは行セットとして表されます。 - 行セットは、行セットに U-SQL 式を適用し、新しい行セットを生成する複数の U-SQL ステートメントで変換されます。
- 最後に、結果の行セットは、場所、組み込みまたはユーザー定義アウトプッターを指定する
OUTPUT
ステートメントと、組み込みまたはユーザー定義アウトプッター、あるいは U-SQL テーブルを使用していずれかのファイルに出力されます。
スクリプトは遅延評価されます。つまり、抽出と変換の各手順は、式ツリーに構成され、グローバルに評価されます (データフロー)。
Spark プログラムは、spark コネクタを使用してデータを読み取り、データフレームを作成した後、LINQ に似た DSL または SparkSQL を使用してデータフレームに変換を適用し、その結果をファイル、一時 Spark テーブル、プログラミング言語の種類、またはコンソールに書き込むという点で似ています。
.NET コードの変換
U-SQL の式言語は C# であり、ユーザー定義関数、ユーザー定義演算子およびユーザー定義集計を使用してカスタム .NET コードをスケールアウトするためのさまざまな方法が提供されます。
Azure Synapse と Azure HDInsight Spark の両方で、.NET for Apache Spark での .NET コードの実行がネイティブにサポートされるようになりました。 これは、Spark で .NET ユーザー定義関数の一部またはすべてを再利用できる可能性があることを意味します。 しかし、U-SQL では.NET Framework が使用されますが、NET for Apache Spark は .NET Core 3.1 以降に基づいていることに注意してください。
U-SQL ユーザー定義演算子 (UDO) では、U-SQL UDO モデルを使用して、演算子のコードのスケールアウトされた実行が提供されます。 したがって、UDF をユーザー定義関数に書き換え、Spark 実行モデルに合わせる必要があります。
.NET for Apache Spark では、現在、ユーザー定義アグリゲーターはサポートされていません。 したがって、U-SQL ユーザー定義アグリゲーターは、Scala で記述された Spark ユーザー定義アグリゲーターに変換する必要があります。
.NET for Apache Spark 機能を利用しない場合は、式を同等の Spark、Scala、Java、または Python 式、関数、アグリゲーター、またはコネクタに書き換える必要があります。
いずれの場合も、U-SQL スクリプトに大量の .NET ロジックがある場合は、詳しいガイダンスについて Microsoft アカウントの担当者にご連絡ください。
ここでは、U-SQL スクリプトでの .NET と C# のさまざまな使用方法について詳しく説明します。
スカラー インライン U-SQL C#式の変換
U-SQL の式言語は C# です。 スカラー インラインの U-SQL 式の多くは、パフォーマンスを向上させるためにネイティブに実装されていますが、.NET フレームワークを呼び出すと、より複雑な式を実行できます。
Spark には、独自のスカラー式言語 (DSL の一部として、または SparkSQL) があり、JVM、.NET または Python ラインタイム用に記述されたユーザー定義関数を呼び出すことができます。
U-SQL にスカラー式が含まれている場合は、パフォーマンスを最大限に引き出すために、ネイティブに認識されている最も適切な Spark スカラー式を見つけてから、選択した Spark ランタイム言語のユーザー定義関数に他の式をマップする必要があります。
.NET と C# は、JVM と Python ランタイムおよび Spark の DSL とは異なる型セマンティクスを持つことに注意してください。 型システムの違いの詳細については、以下を参照してください。
ユーザー定義のスカラー .NET 関数とユーザー定義のアグリゲーターを変換する
U-SQL は、任意のスカラー .NET 関数を呼び出し、.NET で記述されたユーザー定義のアグリゲーターを呼び出します。
Spark は、Spark の DSL と SparkSQL から呼び出すことができる、ほとんどのホスティング言語で記述されたユーザー定義関数およびユーザー定義のアグリゲーターもサポートしています。
前述のように、.NET for Apache Spark では .NET で記述されたユーザー定義関数がサポートされていますが、ユーザー定義アグリゲーターはサポートされていません。 そのため、ユーザー定義関数の場合、.NET for Apache Spark を使用できますが、ユーザー定義アグリゲーターは Scala for Spark で作成する必要があります。
ユーザー定義演算子 (UDO) の変換
U-SQL には、エクストラクター、アウトプッター、レジューサー、プロセッサー、アプライヤー、および .NET (若干の Python と R) で記述できるコンバイナーなど、ユーザー定義演算子 (UDO) のカテゴリがいくつか用意されています。
Spark は演算子に対して同じ機能拡張モデルを提供しませんが、一部では同等の機能を備えています。
Spark でエクストラクターとアウトプッターと同等の機能を持つのが、Spark コネクタです。 多くの U-SQL エクストラクターは、Spark コミュニティに同等のコネクタが存在する可能性があります。 その他の場合は、カスタム コネクタを作成する必要があります。 U-SQL エクストラクターが複雑で、複数の .NET ライブラリを使用している場合は、相互運用機能を使用してデータ処理を実際に行う .NET ライブラリを呼び出すコネクタを、Scala で作成することをお勧めします。 その場合は、.NET Core ランタイムを Spark クラスターにデプロイし、参照されている .NET ライブラリが .NET Standard 2.0 に準拠していることを確認する必要があります。
その他の種類の U-SQL UDO は、ユーザー定義関数とユーザー定義のアグリゲーター、および意味的に適している Spark DLS または SparkSQL 式を使用して書き換える必要があります。 たとえば、プロセッサは、データフレームを引数として受け取り、データフレームを返す関数としてパッケージ化された、さまざまな UDF 呼び出しの SELECT にマップできます。
U-SQL のオプションのライブラリを変換する
U-SQL には、Python、R、JSON、XML、AVRO サポート、および一部の Azure AI サービスの機能が利用できる一連のオプションのデモ ライブラリが用意されています。
Spark はそれぞれ独自の Python と R の統合、pySpark、SparkR を提供し、JSON、XML、AVRO の読み取りと書き込みのためのコネクタを提供します。
Azure AI サービス ライブラリを参照するスクリプトを変換する必要がある場合は、Microsoft アカウント担当者に連絡することをお勧めします。
型指定された値を変換する
U-SQL の型システムは .NET 型システムに基づいており、Spark にはホスト言語のバインドに影響を受ける独自の型システムがあるため、扱っている型が近く、また一部の型では型の範囲、有効桁数、または小数点以下桁数が多少異なる場合があります。 さらに、U-SQL と Spark では null
の値が異なる方法で処理されます。
データ型
次の表は、指定された U-SQL の型に対応する Spark、Scala、PySpark の各型を示しています。
U-SQL | Spark | Scala | PySpark |
---|---|---|---|
byte |
|||
sbyte |
ByteType |
Byte |
ByteType |
int |
IntegerType |
Int |
IntegerType |
uint |
|||
long |
LongType |
Long |
LongType |
ulong |
|||
float |
FloatType |
Float |
FloatType |
double |
DoubleType |
Double |
DoubleType |
decimal |
DecimalType |
java.math.BigDecimal |
DecimalType |
short |
ShortType |
Short |
ShortType |
ushort |
|||
char |
Char |
||
string |
StringType |
String |
StringType |
DateTime |
$ | $ | $ |
bool |
BooleanType |
Boolean |
BooleanType |
Guid |
|||
byte[] |
BinaryType |
Array[Byte] |
BinaryType |
SQL.MAP<K,V> |
MapType(keyType, valueType, valueContainsNull) |
scala.collection.Map |
MapType(keyType, valueType, valueContainsNull=True) |
SQL.ARRAY<T> |
ArrayType(elementType, containsNull) |
scala.collection.Seq |
ArrayType(elementType, containsNull=True) |
詳細については、以下を参照してください:
NULL の扱いについて
Spark では、既定の型ごとに NULL 値が許可されますが、その際、U-SQL では、スカラー、非オブジェクトを null 許容として明示的にマークします。 Spark では、列を null を許容しないものとして定義できますが、制約は適用されず、これによって結果が間違ってしまう可能性があります。
Spark において、NULL は値が認識できないことを示します。 Spark NULL 値は、それ自体を含む任意の値とは異なります。 2 つの Spark NULL 値、または Spark NULL 値と他の値を比較する場合、どの NULL も認識できないので、認識できないことを示す値が返されます。
この動作は、null
がそれ自体以外のどの値とも異なる C#セマンティクスに従う、U-SQL とは異なります。
したがって、WHERE column_name = NULL
を使用する SparkSQL SELECT
ステートメントでは、column_name
に NULL 値がある場合でも 0 行が返され、U-SQL では、column_name
が null
に設定されている行が返されます。 同様に、WHERE column_name != NULL
を使用する Spark SELECT
ステートメントでは、column_name
に 非null 値がある場合でも 0 行が返され、U-SQL では、非 null に設定されている行が返されます。 したがって、U-SQL の null チェック セマンティクスが必要な場合は、isnull および isnotnull (または DSL 同等) をそれぞれ使用する必要があります。
U-SQL カタログ オブジェクトを変換する
大きな違いの 1 つは、U-SQL スクリプトでは、直接的に Spark に同等のものが存在しない独自のカタログ オブジェクトを利用できることです。
Spark では、U-SQL データベースとスキーマを Hive データベースに、および U-SQL テーブルを Spark テーブルにマップできるよう、Hive メタストアの概念 (主にデータベース、テーブルおよびビュー) がサポートされています (U-UQL テーブルに格納されているデータの移動に関する記事を参照)。しかし、テーブル値関数 (TVF)、ストアド プロシージャ、U-SQL アセンブリ、外部データソースなどはサポートされていません。
ビュー、TVF、ストアド プロシージャ、アセンブリなどの U-SQL コード オブジェクトは、Spark のコード関数とライブラリを使用してモデル化し、ホスト言語の関数と手続き型の抽象化メカニズムを使用して (たとえば、Python モジュールのインポートや Scala 関数の参照などを通じて) 参照できます。
プロジェクトおよびチーム間でデータとコード オブジェクトを共有するために U-SQL カタログが使用されている場合は、共有用の同等のメカニズムを使用する必要があります (たとえば、コード オブジェクトを共有するための Maven など)。
U-SQL 行セット式と SQL ベースのスカラー式を変換する
U-SQL のコア言語は、行セットを変換し、SQL に基づいています。 U-SQL で提供される最も一般的な行セット式の一覧 (すべてではありません) を次に示します。
SELECT
/FROM
/WHERE
/GROUP BY
+ 集計 +HAVING
/ORDER BY
+FETCH
INNER
/OUTER
/CROSS
/SEMI
JOIN
式CROSS
/OUTER
APPLY
式PIVOT
/UNPIVOT
式VALUES
行セット コンストラクター設定式
UNION
/OUTER UNION
/INTERSECT
/EXCEPT
さらに、U-SQL には、次のような SQL ベースのさまざまなスカラー式が用意されています。
OVER
ウィンドウ化関数- さまざまな組み込みのアグリゲーターおよび順位付け関数 (
SUM
、FIRST
など) - 最も一般的な SQL スカラー式の一部 (
CASE
、LIKE
、(NOT
)IN
、AND
、OR
など)。
Spark は、これらの式のほとんどに対して、DSL と SparkSQL の両方の形式で同等の式を提供します。 Spark でネイティブにサポートされていない式の一部は、ネイティブの Spark 式と意味的に同等なパターンを組み合わせて書き換える必要があります。 たとえば、OUTER UNION
は、プロジェクションと和集合の同等の組み合わせに変換する必要があります。
NULL 値の処理方法が異なるため、比較対象の列の両方に NULL 値が含まれていている場合 U-SQL 結合は常に行と一致し、Spark の結合は明示的な null チェックが追加されない限り、このような列に一致しません。
その他の U-SQL の概念を変換する
U-SQL は、SQL Server データベースに対するフェデレーションクエリ、パラメーター、スカラー、およびラムダ式の変数、システム変数、OPTION
ヒントなど、他のさまざまな機能や概念も提供します。
SQL Server データベース/外部テーブルに対するフェデレーション クエリ
U-SQL では、データ ソースと外部テーブルだけでなく Azure SQL Database に対する直接クエリも可能です。 Spark は同じオブジェクトの抽象化を提供しませんが、SQL データベースのクエリに使用できる SQL Server 用の Spark コネクタを提供します。
U-SQL パラメーターと変数
Spark とそのホスト言語では、パラメーターとユーザー変数の概念は同じです。
たとえば、Scala では次のように var
キーワードを使用して変数を定義できます。
var x = 2 * 3;
println(x)
U-SQL のシステム変数 (@@
で始まる変数) は、次の 2 つのカテゴリに分けることができます。
- スクリプトの動作に影響を与えるように特定の値に設定できる設定可能なシステム変数
- システムおよびジョブ レベルの情報を照会する情報システム変数
設定可能なシステム変数のほとんどは、Spark に直接対応していません。 情報システム変数の中には、ジョブの実行中に引数として情報を渡すことによってモデル化できるものもあれば、Spark のホスト言語で同等の機能が利用できるものもあります。
U-SQL のヒント
U-SQL では、クエリ オプティマイザーと実行エンジンにヒントを与える構文方法がいくつか提供されています。
- U-SQL システム変数を設定する
- 行セット式に関連付けることでデータまたはプランのヒントを提供する
OPTION
句 - JOIN 式の構文の結合ヒント (
BROADCASTLEFT
など)
Spark のコストベースのクエリ オプティマイザーには、ヒントを提供し、クエリのパフォーマンスを調整するための独自の機能があります。 対応するドキュメントをご覧ください。