U-SQL 開発者向けの Apache Spark コードについて

重要

Azure Data Lake Analyticsは、2024 年 2 月 29 日に廃止されました。 詳細については、このお知らせを参照してください。

データ分析の場合、organizationは Azure Synapse Analytics または Microsoft Fabric を使用できます。

このセクションでは、U-SQL スクリプトの Apache Spark への変換に関する概要を説明します。

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 スクリプトを一連の Spark と、Azure BatchまたはAzure Functionsで実装されたその他の手順に分割することが必要になる場合があります。

さらに、Azure Data Lake Analytics では、各ジョブにリソースが割り当てられるサーバーレス ジョブ サービス環境で U-SQL が提供されますが、Azure Synapse Spark、Azure Databricks、Azure HDInsight では、クラスター サービスの形式またはいわゆる Spark プール テンプレートを使用して Spark が提供されます。 アプリケーションを変換するときは、クラスターまたはプールの作成、サイズ変更、スケーリング、使用停止の影響を考慮する必要があります。

U-SQL スクリプトの変換

U-SQL スクリプトは、次の処理パターンに従います。

  1. データは、場所またはファイルセットを指定する EXTRACT ステートメント、組み込みまたはユーザー定義のエクストラクターおよび必要なスキーマを使用して非構造化ファイルから読み取られるか、U-SQL テーブル (マネージテーブルまたは外部テーブル) から読み取られます。 行セットとして表されます。
  2. 行セットは、行セットに U-SQL 式を適用し、新しい行セットを生成する複数の U-SQL ステートメントで変換されます。
  3. 最後に、結果の行セットは、場所、組み込みまたはユーザー定義アウトプッターを指定する 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 には、 PythonRJSON、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 DateType, TimestampType java.sql.Date, java.sql.Timestamp DateType, TimestampType
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_namenull に設定されている行が返されます。 同様に、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/SEMIJOIN

  • CROSS/OUTERAPPLY

  • PIVOT/UNPIVOT

  • VALUES 行セット コンストラクター

  • 設定式 UNION/OUTER UNION/INTERSECT/EXCEPT

さらに、U-SQL には、次のようなさまざまな SQL ベースのスカラー式が用意されています。

  • OVER ウィンドウ化関数
  • さまざまな組み込みアグリゲーターとランク付け関数 (SUMFIRSTなど)
  • 最も一般的な SQL スカラー式の一部 (CASELIKE、(NOT) INANDOR など)。

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 データベースのクエリに使用できる Azure SQL Database 用の 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 のコストベースのクエリ オプティマイザーには、ヒントを提供し、クエリのパフォーマンスを調整するための独自の機能があります。 対応するドキュメントを参照してください。

次のステップ