効率的に Batch リソースを一覧表示するクエリを作成する

ほとんどの Azure Batch アプリケーションは、監視を行ったり Batch サービスにクエリを実行するその他の操作を行います。 多くの場合、このようなリスト クエリは一定の間隔で発生します。 たとえば、ジョブのキューに登録されたタスクを確認する前に、そのジョブのすべてのタスクについてデータを取得する必要があります。 クエリに対してバッチ サービスから返されるデータ量を減らすと、アプリケーションのパフォーマンスが向上します。 この記事では、このようなクエリを最も効率的な方法で実行する方法について説明します。 Batch .NET ライブラリを使用して、バッチ ジョブ、タスク、コンピューティング ノード、およびその他のリソースに対してフィルター処理されたクエリを作成できます。

Note

Batch サービスは、一般的なシナリオ (ジョブ内のタスクのカウントと Batch プール内のコンピューティング ノードのカウント) 用の API をサポートしています。 リスト クエリを使用する代わりに、Get Task Counts 操作と List Pool Node Counts 操作を呼び出すことができます。 ただし、このようにより効率的な操作では、より限定的な情報が返されることになり、その情報が最新でない可能性があります。 詳細については、状態ごとのタスクとコンピューティング ノードのカウントに関するページを参照してください。

詳細レベルを指定する

運用環境の Batch アプリケーションでは、ジョブ、タスク、計算ノードのようなエンティティは数千単位になることがあります。 リソースに対して実行するクエリごとに、大量のデータが Batch サービスからアプリケーションに送信される可能性があります。 パフォーマンスを向上させるためにクエリから返される項目の数と情報を制限します。

次の Batch .NET API コード スニペットは、ジョブに関連付けられているすべてのタスクと、各タスクのすべてのプロパティを取得します。

// Get a collection of all of the tasks and all of their properties for job-001
IPagedEnumerable<CloudTask> allTasks =
    batchClient.JobOperations.ListTasks("job-001");

詳細レベルをクエリに適用すると、情報がより効率的に表示されます。 具体的には、ODATADetailLevel オブジェクトを JobOperations.ListTasks メソッドに指定します。 次のスニペットでは、完了したタスクの ID、コマンド ライン、計算ノード情報のプロパティだけが返されます。

// Configure an ODATADetailLevel specifying a subset of tasks and
// their properties to return
ODATADetailLevel detailLevel = new ODATADetailLevel();
detailLevel.FilterClause = "state eq 'completed'";
detailLevel.SelectClause = "id,commandLine,nodeInfo";

// Supply the ODATADetailLevel to the ListTasks method
IPagedEnumerable<CloudTask> completedTasks =
    batchClient.JobOperations.ListTasks("job-001", detailLevel);

この例のシナリオでジョブに何千ものタスクがある場合、通常は 2 つ目のクエリの結果は最初のものより速く返されます。 Batch .NET API を使用して項目を一覧表示するときの ODATADetailLevel の使用方法の詳細については「Batch .NET での効率的なクエリ実行」セクションを参照してください。

重要

アプリケーションの最大限の効率とパフォーマンスを確保するために、.NET API リスト呼び出しには常に ODATADetailLevel オブジェクトを指定することを強くお勧めします。 詳細レベルを指定することによって、Batch サービスの応答時間の短縮、ネットワーク使用率の改善、クライアント アプリケーションによるメモリ使用量の最小化といった効果が期待できます。

クエリ文字列を使用する

Batch .NETおよびBatch REST API を使用して、クエリが返す項目の数と、各項目に対してクエリが返す情報の量を減らすことができます。 クエリを絞り込むために使用できるクエリ文字列型には、 $filter$select、および $expand の3つがあります。

Batch .NET API については、「ODATADetailLevel Class プロパティ」を参照してください。 また、「Batch .NET での効率的なクエリ実行」も参照してください。

Batch REST API については、「Batch REST API リファレンス」を参照してください。 クエリを実行するリソースの リスト 参照を見つけます。 次に、$filter$select、および $expand の詳細については、「 URI パラメーター 」セクションを参照してください。 たとえば、「プールの URI パラメーター - リスト」を参照してください。 また「Azure CLI を使用して効率的なバッチクエリを作成する方法」についても説明します。

注意

3 種類のクエリ文字列のいずれかを組み立てる際に、プロパティ名および大文字と小文字が REST API 要素と一致することを確認する必要があります。 たとえば、.NET CloudTask クラスを使用する場合は、.NET プロパティが CloudTask.State であっても、State の代わりに state を指定する必要があります。 詳細は、「.NET と REST API 間のプロパティ マッピング」を参照してください。

フィルター

$filter 式の文字列は、返される項目の数を減らす式です。 たとえば、あるジョブの実行中のタスクのみ、またはタスクの実行準備が完了しているコンピューティング ノードのみをリストできます。

この文字列は、プロパティ名、演算子、値で構成される 1 つ以上の式からなります。 指定できるプロパティは、クエリする各エンティティ型に固有です。各エンティティでサポートされる演算子も同様です。 論理演算子の andor を使用して、複数の式を結合できます。

この例では、実行中のレンダリング タスクのみをリストします: (state eq 'running') and startswith(id, 'renderTask')

選択

$select 式の文字列は、各項目に対して返されるプロパティの値を制限します。 カンマ区切りのプロパティ名の一覧を指定すると、指定されたプロパティ値のみがクエリ結果で返されます。 クエリするエンティティ型のすべてのプロパティを指定できます。

この例では、各タスクで 3 つのプロパティ値のみを返すように指定します: id, state, stateTransitionTime

Expand

$expand 式の文字列は、特定の情報を取得するために必要な API 呼び出しの数を減らします。 この文字列を使用すると、1 つの API 呼び出しで各項目に関する詳細情報を取得できます。 この方法では、API 呼び出しを減らすことでパフォーマンスを向上させることができます。 エンティティの一覧を取得し、各リスト項目に関する情報を要求するのではなく、$expand 文字列を使用します。

$select と同様に、$expand はリスト クエリ結果に特定のデータを含めるかどうかを制御します。 すべてのプロパティが必要なときに select 文字列が指定されていない場合は、$expand を使用して統計情報を取得する必要があります。 select 文字列を使用してプロパティのサブセットを取得する場合は、stats を select 文字列に指定でき、$expand を指定する必要はありません。

この文字列には、ジョブ、ジョブ スケジュール、タスク、およびプールの一覧表示がサポートされています。 現在サポートされているのは統計情報のみです。

この例では、一覧の各項目に統計情報が返されるように指定するします: stats

filter、select、expand 文字列の規則

  • filter、select、expand 文字列のプロパティ名は、Batch REST API に表示される場合のプロパティ名と同じであることを確認してください。 この規則は、 Batch .NET または他のいずれかの Batch SDK を使用する場合にも適用されます。
  • すべてのプロパティ名では大文字と小文字が区別されますが、プロパティの値は大文字と小文字を区別しません。
  • 日付/時刻文字列は、次の 2 つの形式のいずれかを使用でき、前に DateTimeを付ける必要があります。
    • W3C-DTF 形式の例: creationTime gt DateTime'2011-05-08T08:49:37Z'
    • RFC 1123 形式の例: creationTime gt DateTime'Sun, 08 May 2011 08:49:37 GMT'
  • ブール文字列は、truefalse のいずれかです。
  • 無効なプロパティまたは演算子を指定すると、 400 (Bad Request) エラーが発生します。

Batch .NET の効率的クエリ

Batch .NET API 内で、ODATADetailLevel クラスを使用して、リスト操作に対して filter、select、expand 文字列を指定しますODataDetailLevel クラスには、3 つのパブリック文字列プロパティがあります。 これらのプロパティは、コンストラクターで指定することも、オブジェクトのプロパティを直接設定することもできます。 そのうえで、ListPoolsListJobsListTasks などの各種リスト操作のパラメーターとして、ODataDetailLevel オブジェクトを渡します。

次のコード スニペットでは Batch .NET API を使用して、特定のプール セットの統計値を Batch サービスに効率的に問い合わせます。 Batch ユーザーにはテスト プールと運用プールの両方が与えられています。 テスト プールの ID 接頭辞は "test" であり、運用プールの ID 接頭辞は "prod" です。 myBatchClientBatchClient クラスの適切に初期化されたインスタンスです。

// First we need an ODATADetailLevel instance on which to set the filter, select,
// and expand clause strings
ODATADetailLevel detailLevel = new ODATADetailLevel();

// We want to pull only the "test" pools, so we limit the number of items returned
// by using a FilterClause and specifying that the pool IDs must start with "test"
detailLevel.FilterClause = "startswith(id, 'test')";

// To further limit the data that crosses the wire, configure the SelectClause to
// limit the properties that are returned on each CloudPool object to only
// CloudPool.Id and CloudPool.Statistics
detailLevel.SelectClause = "id, stats";

// Specify the ExpandClause so that the .NET API pulls the statistics for the
// CloudPools in a single underlying REST API call. Note that we use the pool's
// REST API element name "stats" here as opposed to "Statistics" as it appears in
// the .NET API (CloudPool.Statistics)
detailLevel.ExpandClause = "stats";

// Now get our collection of pools, minimizing the amount of data that is returned
// by specifying the detail level that we configured above
List<CloudPool> testPools =
    await myBatchClient.PoolOperations.ListPools(detailLevel).ToListAsync();

ヒント

Select 句と Expand 句で構成される ODATADetailLevel のインスタンスも、返されるデータの量を制限するために、PoolOperations.GetPool などの適切な Get メソッドに渡すことができます。

Batch REST から NET API へのマッピング

filter、select、および expand 文字列のプロパティ名は、REST API の対応部分の名前および大文字と小文字の両方を反映している必要があります。 次の表では、.NET および REST API の対応部分の間のマッピングを示します。

filter 文字列のマッピング

  • .NET リスト メソッド:この列の各 .NET API メソッドは、ODATADetailLevel オブジェクトをパラメーターとして受け付けます。
  • REST リスト要求: この列のリストされる REST API ページには、 filter 文字列で許可されるプロパティと操作を指定する表が含まれています。 ODATADetailLevel.FilterClause 文字列を構築するときに、これらのプロパティ名と操作を使用します。
.NET リスト メソッド REST リスト要求
CertificateOperations.ListCertificates アカウントの証明書を一覧表示する
CloudTask.ListNodeFiles タスクに関連付けられているファイルを一覧表示する
JobOperations.ListJobPreparationAndReleaseTaskStatus ジョブのジョブ準備タスクとジョブ リリース タスクの状態を一覧表示する
JobOperations.ListJobs アカウントのジョブを一覧表示する
JobOperations.ListNodeFiles ノードのファイルを一覧表示する
JobOperations.ListTasks ジョブに関連付けられているタスクを一覧表示する
JobScheduleOperations.ListJobSchedules アカウントのジョブ スケジュールを一覧表示する
JobScheduleOperations.ListJobs ジョブ スケジュールに関連付けられているジョブを一覧表示する
PoolOperations.ListComputeNodes プールのコンピューティング ノードを一覧表示する
PoolOperations.ListPools アカウントのプールを一覧表示する

select 文字列のマッピング

  • Batch .NET の型:Batch .NET API の型です。
  • REST API のエンティティ:この列内の各ページには、その型の REST API プロパティ名を列挙した表が 1 つ以上含まれています。 select 文字列を構築する際に、これらのプロパティ名が使用されます。 ODATADetailLevel.SelectClause 文字列を構築するときに、これらの同じプロパティ名を使用します。
Batch .NET の型 REST API のエンティティ
[MSSQLSERVER のプロトコルのプロパティ] 証明書に関する情報を取得する
CloudJob ジョブに関する情報を取得する
CloudJobSchedule ジョブ スケジュールに関する情報を取得する
ComputeNode ノードに関する情報を取得する
CloudPool プールに関する情報を取得する
CloudTask タスクに関する情報を取得する

例: filter 文字列の構築

ODATADetailLevel.FilterClause のフィルター文字列を作成するには、対応する REST API ページを探します。 選択できるプロパティとそのサポートされる演算子は、最初の複数行テーブル内に表示されます。 たとえば、終了コードがゼロ以外のタスクをすべて取得する場合は、ジョブに関連付けられているタスクの一覧表示を確認し、適用可能なプロパティ文字列と許可される演算子を指定します:

プロパティ 許可される操作 Type
executionInfo/exitCode eq, ge, gt, le , lt Int

関連するフィルター文字列:

(executionInfo/exitCode lt 0) or (executionInfo/exitCode gt 0)

例: select 文字列の構築

ODATADetailLevel.SelectClause を構築するには、リストするエンティティに対応する REST API ページを見つけてください。 選択できるプロパティとそのサポートされる演算子は、最初の複数行テーブル内に表示されます。 たとえば、リスト内の各タスクの ID とコマンド ラインのみを取得するには、タスクに関する情報の取得に関するページを参照してください:

プロパティ Type メモ
id String The ID of the task.
commandLine String The command line of the task.

関連する select 文字列は次の形式です:

id, commandLine

コード サンプル

効率的なリスト クエリ

EfficientListQueries サンプル プロジェクトは、効率的なリスト クエリがアプリケーションのパフォーマンスにどのように影響するかを示しています。 この C# コンソール アプリケーションは、大量のタスクを作成してジョブに追加します。 次に、アプリケーションは JobOperations.ListTasks メソッドに対して複数の呼び出しを行い、ODATADetailLevel オブジェクトを渡します。 これらのオブジェクトは、返されるデータの量を変更するために、異なるプロパティ値で構成されます。 このサンプルでは、次のような出力が生成されます:

Adding 5000 tasks to job jobEffQuery...
5000 tasks added in 00:00:47.3467587, hit ENTER to query tasks...

4943 tasks retrieved in 00:00:04.3408081 (ExpandClause:  | FilterClause: state eq 'active' | SelectClause: id,state)
0 tasks retrieved in 00:00:00.2662920 (ExpandClause:  | FilterClause: state eq 'running' | SelectClause: id,state)
59 tasks retrieved in 00:00:00.3337760 (ExpandClause:  | FilterClause: state eq 'completed' | SelectClause: id,state)
5000 tasks retrieved in 00:00:04.1429881 (ExpandClause:  | FilterClause:  | SelectClause: id,state)
5000 tasks retrieved in 00:00:15.1016127 (ExpandClause:  | FilterClause:  | SelectClause: id,state,environmentSettings)
5000 tasks retrieved in 00:00:17.0548145 (ExpandClause: stats | FilterClause:  | SelectClause: )

Sample complete, hit ENTER to continue...

プロパティと返される項目の数を制限することで、クエリの応答時間を大幅に短縮できることを示す例です。 このサンプル プロジェクトと他のサンプル プロジェクトは、GitHub の azure-batch-samples リポジトリにあります。

BatchMetrics ライブラリ

以下の BatchMetrics サンプル プロジェクトには、Batch API を使って Azure Batch ジョブの進行状況を効率的に監視する方法が紹介されています。

このサンプルには、独自のプロジェクトに組み込む .NET クラス ライブラリ プロジェクトが含まれています。 また、ライブラリの使用を実行してデモを行う簡単なコマンドライン プログラムもあります。

プロジェクト内のサンプル アプリケーションでは、これらの操作が示されています:

  • 必要なプロパティだけをダウンロードするために特定の属性を選択します
  • 前回のクエリ以降に行われた変更のみをダウンロードするために状態遷移の時刻を条件としてフィルタリングします

たとえば BatchMetrics ライブラリには、以下のメソッドが存在します。 このメソッドは、照会したエンティティの id プロパティと state プロパティのみを取得するよう指定する ODATADetailLevel を返します。 この ODATADetailLevel には、パラメーターに指定された DateTime 以降に状態が変化したエンティティのみを取得するための指定も含まれています。

internal static ODATADetailLevel OnlyChangedAfter(DateTime time)
{
    return new ODATADetailLevel(
        selectClause: "id, state",
        filterClause: string.Format("stateTransitionTime gt DateTime'{0:o}'", time)
    );
}

次のステップ