Microsoft Azure Storage のパフォーマンスとスケーラビリティに対するチェック リスト

Overview

Microsoft Azure Storage サービスのリリース以来、Microsoft はこれらのサービスを使用して優れたパフォーマンスを達成するための実証済みプラクティスを数多く開発してきました。この記事では、特に重要なプラクティスを選んでチェック リスト形式の一覧にまとめています。 この記事は、アプリケーション開発者が Azure Storage で実証済みプラクティスを使用しているかどうかを確認し、適用の検討が望ましい他の実証済みプラクティスを特定するための資料です。 実行可能なパフォーマンスとスケーラビリティの最適化を網羅するものではなく、影響が小さいプラクティスや適用範囲の狭いプラクティスは除外しています。 設計時に予測できる範囲で、早い段階からアプリケーションの動作に留意しておくことは、パフォーマンスの問題につながる設計を避けるために有用です。

Azure Storage を使用するアプリケーション開発者は、この記事をじっくり読み、自分のアプリケーションが下のリストの実証済みプラクティスに従っていることを確認してください。

チェック リスト

この記事では、実証済みのプラクティスを次のグループにまとめてあります。 実証済みのプラクティスは、以下のサービスを対象とします。

  • すべての Azure Storage サービス (BLOB、テーブル、キュー、ファイル)。
  • BLOB
  • テーブル
  • キュー
完了 領域 カテゴリ 質問
  すべてのサービス スケーラビリティ ターゲット アプリケーションは、スケーラビリティ ターゲットへの接近を回避する設計になっていますか?
  すべてのサービス スケーラビリティ ターゲット 命名規則は負荷分散を向上できるように設計されていますか?
  すべてのサービス ネットワーク クライアント側デバイスは、必要なパフォーマンスを達成するのに十分な帯域幅を低遅延で利用できますか?
  すべてのサービス ネットワーク クライアント側のデバイスは十分に質の高い接続を保持していますか?
  すべてのサービス ネットワーク クライアント アプリケーションはストレージ アカウントの "近く" に配置されていますか?
  すべてのサービス コンテンツ配信 コンテンツ配信に CDN を使用していますか?
  すべてのサービス クライアントへの直接アクセス プロキシではなく、SAS と CORS を使用して、ストレージへの直接アクセスを許可していますか?
  すべてのサービス Caching (キャッシュ) 繰り返し使用し、ほとんど変更されないデータをアプリケーションでキャッシュしていますか?
  すべてのサービス Caching (キャッシュ) アプリケーションでバッチ更新 (クライアント側でキャッシュし、より大きなセットにアップロードする方法) を実行していますか?
  すべてのサービス .NET 構成 十分な数の同時接続を使用するようにクライアントを構成していますか?
  すべてのサービス .NET 構成 十分な数のスレッドを使用するように .NET を構成していますか?
  すべてのサービス .NET 構成 ガベージ コレクション機能が向上した .NET 4.5 以降を使用していますか?
  すべてのサービス 並列処理 クライアントの機能やスケーラビリティ ターゲットに過剰な負荷がかからないように、並列処理を適切に制限していますか?
  すべてのサービス ツール Microsoft が提供する最新バージョンのクライアント ライブラリとツールを使用していますか?
  すべてのサービス 再試行 エラーとタイムアウトの調整に、指数関数的バックオフによる再試行ポリシーを使用していますか?
  すべてのサービス 再試行 再試行できないエラーに対するアプリケーションの再試行を回避していますか?
  BLOB スケーラビリティ ターゲット 1 つのオブジェクトに多数のクライアントが同時にアクセスしますか?
  BLOB スケーラビリティ ターゲット 1 つの BLOB に関する帯域幅または操作のスケーラビリティ ターゲット内に、アプリケーションが収まっていますか?
  BLOB BLOB のコピー 効率的な方法で BLOB をコピーしていますか?
  BLOB BLOB のコピー BLOB の一括コピーに AzCopy を使用していますか?
  BLOB BLOB のコピー きわめて大量のデータ転送に Azure のインポート/エクスポートを使用していますか?
  BLOB メタデータの使用 BLOB に関するメタデータで頻繁に使用するものを、その BLOB のメタデータに格納していますか?
  BLOB 迅速なアップロード 1 つの BLOB を迅速にアップロードするときに、ブロックを並列アップロードしていますか?
  BLOB 迅速なアップロード 多数の BLOB を迅速にアップロードするときに、ブロックを並列アップロードしていますか?
  BLOB 正しい BLOB の種類 適宜、ページ BLOB やブロック BLOB を使用していますか?
  テーブル スケーラビリティ ターゲット 1 秒あたりのエンティティに対するスケーラビリティ ターゲットに近づいていませんか?
  テーブル 構成 テーブル要求に JSON を使用していますか?
  テーブル 構成 小さな要求のパフォーマンスを上げるために、Nagle をオフにしていますか?
  テーブル テーブルとパーティション 適切にデータのパーティション分割を実行していますか?
  テーブル ホット パーティション 末尾または先頭にのみ追加されるパターンを回避していますか?
  テーブル ホット パーティション 多くのパーティションにまたがる挿入や更新を実行しますか?
  テーブル クエリ スコープ ほとんどの場合にポイント クエリの使用を許可し、テーブル クエリは控え目に使用するようスキーマを設計していますか?
  テーブル クエリ密度 通常のクエリでは、アプリケーションが今後使用する行のみをスキャンして結果を取得していますか?
  テーブル 返されるデータの限定 不要なエンティティが返されないように、フィルターを使用していますか?
  テーブル 返されるデータの限定 不要なプロパティが返されないように、プロジェクションを使用していますか?
  テーブル 非正規化 データを取得するときに非効率なクエリや複数の読み取り要求が回避されるように、データを非正規化していますか?
  テーブル 挿入/更新/削除 トランザクションとする必要がある要求やラウンド トリップを削減するために同時に実行できる要求は、バッチ操作で実行していますか?
  テーブル 挿入/更新/削除 挿入または更新のどちらを実行するかを判断するためだけにエンティティを取得しないようにしていますか?
  テーブル 挿入/更新/削除 まとめて取得されることが多い一連のデータは、複数のエンティティではなく、1 つのエンティティにプロパティとして格納することを検討しましたか?
  テーブル 挿入/更新/削除 常にまとめて取得され、バッチ操作で書き込むことができるエンティティ (時系列データなど) には、テーブルではなく BLOB を使用することを検討しましたか?
  キュー スケーラビリティ ターゲット 1 秒あたりのメッセージに対するスケーラビリティ ターゲットに近づいていませんか?
  キュー 構成 小さな要求のパフォーマンスを上げるために、Nagle をオフにしていますか?
  キュー メッセージ サイズ キューのパフォーマンスが向上するようにメッセージをコンパクトにしていますか?
  キュー 一括取得 1 回の "Get" 操作で複数のメッセージを取得していますか?
  キュー ポーリング頻度 アプリケーションの知覚可能な遅延を減らすために、ポーリング頻度は十分ですか?
  キュー 更新メッセージ エラー発生時にメッセージ全体の再処理が必要になる事態を回避するために、UpdateMessage を使用してメッセージ処理中の進捗を格納していますか?
  キュー アーキテクチャ キューを使用して、クリティカル パスから長期間のワークロードを外し、アプリケーション全体の拡張性を高めて、その後、個別に規模を設定していますか?

すべてのサービス

このセクションでは、任意の Azure Storage サービス (BLOB、テーブル、キュー、ファイル) を使用する場合に適用できる実証済みプラクティスを列挙します。

スケーラビリティ ターゲット

各 Azure Storage サービスには、容量 (GB)、トランザクション レート、帯域幅についてのスケーラビリティ ターゲットが設定されています。 運用中のアプリケーションがいずれかのスケーラビリティ ターゲットに近づいたり超過したりすると、トランザクション待機時間や調整が増加することがあります。 Storage サービスは、アプリケーションの調整時に、まず一部のストレージ トランザクションに関して、エラー コード "503 サーバーはビジー状態" または "500 操作タイムアウト" を返します。 このセクションでは、スケーラビリティ ターゲット、特に帯域幅のスケーラビリティ ターゲットに対応する一般的な方法を示します。 また、後のセクションでは個々のストレージ サービスを取り上げ、特定のサービスを使用する状況でのスケーラビリティ ターゲットについて説明します。

すべてのサービスに対する帯域幅のスケーラビリティ ターゲット

この記事の執筆時点で、米国での地理冗長ストレージ (GRS) アカウントに対する帯域幅ターゲットは、受信 (ストレージ アカウントに送信されるデータ) の場合に 10 Gbps、送信 (ストレージ アカウントから送信されるデータ) の場合に 20 Gbps です。 ローカル冗長ストレージ (LRS) アカウントでは、この上限がより高く、受信で 20 Gbps、送信で 30 Gbps です。 国際的な帯域幅制限はこれよりも低い場合があるため、 スケーラビリティ ターゲットに関するページを参照してください。 ストレージの冗長オプションの詳細については、後の「 有用な情報 」のリンク先を参照してください。

スケーラビリティ ターゲットに近づいている場合の対処法

アプリケーションが 1 つのストレージ アカウントに対するスケーラビリティ ターゲットに接近している場合は、次の方法のいずれかを検討し、適用します。

  • 対象のアプリケーションでスケーラビリティ ターゲットに対する接近や超過を引き起こしたワークロードを見直します。 設計を変更して、必要な帯域幅や処理能力を抑えたり、トランザクションを減らしたりすることができないでしょうか?
  • アプリケーションが確実にいずれかのスケーラビリティ ターゲットを超過する場合は、複数のストレージ アカウントを作成し、それらのアカウントにアプリケーション データを分けて配置します。 このパターンを使用する場合は、後で負荷分散用のストレージ アカウントを追加できるようにアプリケーションを設計してください。 この記事の執筆時点で、Azure サブスクリプションごとに最大 100 個のストレージ アカウントを作成できます。 また、ストレージ アカウントでは、データ保存、トランザクション実行、データ転送以外の使用に料金が発生することはありません。
  • アプリケーションが帯域幅ターゲットに達する場合は、クライアント側でデータを圧縮し、ストレージ サービスへのデータ送信に必要な帯域幅を削減する方法を検討します。 これにより帯域幅の節約とネットワーク パフォーマンスの改善が期待できますが、マイナスの影響が及ぶ場合もあります。 この方法を適用すると、クライアント側でデータの圧縮と展開の処理要件が増加するため、それがパフォーマンスにどのような影響を及ぼすかを評価する必要があります。 さらに、圧縮データを保存すると、標準のツールでそれらのデータを表示しにくくなるため、問題のトラブルシューティングがより困難になります。
  • アプリケーションがスケーラビリティ ターゲットに達する場合は、再試行に指数関数的バックオフを使用していることを確認してください (「 再試行」を参照)。 望ましいのは、前の方法のいずれかを使用して、スケーラビリティ ターゲットに近づけないことですが、そうするとアプリケーションを迅速に再試行できなくなり、調整の質が低下します。

有用な情報

以下のリンクから、スケーラビリティ ターゲットに関する詳細を確認できます。

パーティションの命名規則

Azure Storage では、範囲を基にしたパーティション構成を使用して、システムを拡大縮小および負荷分散します。 データを範囲にパーティション分割するには、パーティション キーが使用されます。これらの範囲はシステム全体にわたって負荷分散されます。 これは、構文の順序 (例: msftpayroll、msftperformance、msftemployees など) やタイムスタンプの使用 (log20160101、log20160102、log20160102 など) のような命名規則が、負荷分散の操作でより小さな範囲にパーティションを分割されるまで、同じパーティション サーバー上に併置される可能性のあるパーティションに適合されることを意味します。 たとえば、コンテナー内のすべての BLOB は、これらの BLOB の負荷がさらにパーティション範囲の再調整を必要とするまで、1 台のサーバーで提供されます。 同様に、名前が構文の順序で配置された負荷の軽いアカウントのグループは、これらの 1 つまたはすべてのアカウントの負荷が複数のパーティション サーバーに分割される必要があるときまで、1 台のサーバーで提供できます。 負荷分散の各操作は、操作中のストレージの呼び出しの待機時間に影響を与える可能性があります。 パーティションに対して急激に増加したトラフィックを処理するシステムの機能は、負荷分散の操作が開始され、パーティション キーの範囲に再調整されるまで、1 台のパーティション サーバーのスケーラビリティによって制限されます。

このような操作の頻度を減らすために、ベスト プラクティスに従うことができます。

  • アカウント、コンテナー、BLOB、テーブルおよびキューに対して、密接に使用する命名規則を確認します。 お客様のニーズに最も適したハッシュ関数を使用して、アカウント名に 3 桁のハッシュでプレフィックスを付けることを検討します。
  • タイムスタンプまたは数値識別子を使用してデータを整理する場合は、末尾にのみ (または先頭にのみ) 追加されるトラフィック パターンを使用していないことを確認する必要があります。 これらのパターンは、範囲ベースのパーティション分割システムには適していません。すべてのトラフィックを 1 つのパーティションに向けたり、システムを効果的な負荷分散から制限したりする場合があります。 たとえば、yyyymmdd などのタイムスタンプを持つ BLOB オブジェクトを使用する毎日の操作がある場合、毎日の操作に対するすべてのトラフィックが、1 台のパーティション サーバーで提供される 1 つのオブジェクトに直接送信されます。 BLOB の制限およびパーティションの制限ごとにお客様のニーズを満たすかどうかを確認して、必要に応じて、この操作を複数の BLOB に分割することを検討します。 同様に、時系列データをテーブルに保存する場合、すべてのトラフィックをキーの名前空間の最後の部分に直接送信することができます。 タイムスタンプまたは数値 ID を使用する必要がある場合は、3 桁のハッシュを使用して ID にプレフィックスを付けます。また、タイムスタンプの場合は、ssyyyymmdd のように時刻の秒の部分を使用したプレフィックスを付けます。 操作の一覧およびクエリを繰り返し実行する場合は、クエリの数を制限するハッシュ関数を選択します。 その他の場合は、ランダムなプレフィックスが望ましい場合があります。
  • Azure Storage で使用されるパーティション構成の詳細については、 こちらの SOSP ペーパーを参照してください。

ネットワーク

API 呼び出しは重要ですが、一方で、アプリケーションの物理的ネットワークに存在する制約がパフォーマンスに大きな影響を及ぼすことも少なくありません。 以下では、ユーザーが遭遇するいくつかの制限について説明します。

クライアントのネットワーク機能

スループット

帯域幅については、多くの場合にクライアントの処理能力が問題になります。 たとえば、単一のストレージ アカウントで 10 Gbps 以上の受信データを処理できる (「すべてのサービスに対する帯域幅のスケーラビリティ ターゲット」を参照) 一方で、"小さい" Azure worker ロール インスタンスのネットワーク速度が 100 Mbps 程度であるなどの場合です。 大きい Azure インスタンスは、処理能力の高い NIC を使用します。そのため、1 台のコンピューターのネットワーク制限を引き上げる必要がある場合は、大きなインスタンスを使用するか VM の数を増やすことを検討してください。 オンプレミスのアプリケーションからストレージ サービスにアクセスし、同じ規則を適用する場合は、クライアント デバイスのネットワーク性能と、Azure Storage の場所へのネットワーク接続について把握し、それらを必要に応じて増強するか、それぞれの性能の範囲内でアプリケーションが稼働するように設計します。

他のネットワーク運用と同様に、エラーやパケット損失が生じるネットワーク状態では、遅延が生じて有効なスループットが損なわれます。 WireShark または NetMon は、この問題の診断に有用です。

有用な情報

仮想マシンのサイズと割り当てられている帯域幅の詳細については、「Windows VM のサイズ」または「Linux VM のサイズ」をご覧ください。

場所

分散型環境では、サーバーの近くにクライアントを配置すると、パフォーマンスが最大になります。 最小限の遅延で Azure Storage にアクセスするには、同じ Azure リージョン内にクライアントを配置するのが最適です。 たとえば、Azure Storage で Azure Web Sites のサイトを 1 つ保有している場合は、Azure Storage とサイトの両方を単一のリージョン内に配置します (たとえば、米国西部や東南アジア)。 これにより遅延とコストは低下します。執筆時点では、1 つのリージョン内での帯域幅使用は無料です。

クライアント アプリケーションが Azure 内にホストされていない場合 (モバイル デバイス アプリケーションやオンプレミスのエンタープライズ サービス) も、アクセス元のデバイスに近いリージョンにストレージ アカウントを配置すると、一般的に遅延は少なくなります。 クライアントが広範囲に分散されている場合 (一部が北米に、一部がヨーロッパに存在する場合など) は、複数のストレージ アカウントを使用することを検討します。たとえば、アカウントを北米リージョンに配置し、別のアカウントをヨーロッパ リージョンに配置します。 こうすることで、両方のリージョンのユーザーにとって遅延が減少します。 アプリケーションが保存するデータが個々のユーザーに固有であり、ストレージ アカウント間でデータをレプリケーションする必要がなければ、通常は導入しやすい方法です。 広範なコンテンツ配信には、CDN をお勧めします。詳細については、次のセクションを参照してください。

コンテンツ配信

Web サイトのホーム ページに表示される製品デモ ビデオのように、1 つのアプリケーションで、同じリージョンまたは複数リージョン内の多数のユーザーに共通のコンテンツを提示する場合があります。 こうしたシナリオでは、Azure CDN などの Content Delivery Network (CDN) を使用し、Azure Storage を CDN のデータ配信元とします。 Azure Storage アカウントは 1 つのリージョンに存在して、他のリージョンに低遅延でコンテンツを配信できないのに対し、Azure CDN は世界中の異なるデータ センターに存在するサーバーを使用します。 また、通常、CDN は単一のストレージ アカウントよりもはるかに高い送信上限をサポートします。

Azure CDN の詳細については、「 Azure CDN」を参照してください。

SAS と CORS の使用

ユーザーの Web ブラウザーやモバイル アプリケーションで Azure Storage のデータにアクセスする JavaScript などのコードを承認する必要がある場合は、アプリケーションを Web ロールでプロキシとして使用する方法があります。ユーザーのデバイスは Web ロールで認証を実行し、次にストレージ サービスで認証を行います。 この方法では、安全でないデバイスにストレージ アカウント キーを知らせずに済みます。 しかし、ユーザーのデバイスとストレージ サービス間で転送されるデータがすべて、Web ロールを通過するため、Web ロールに大きなオーバーヘッドが生じます。 Shared Access Signature (SAS) を使用すると、Web ロールをストレージ サービスのプロキシとして用いることを回避できます。場合によっては、SAS とクロス オリジン リソース共有 (CORS) ヘッダーと組み合わせて使用します。 SAS を使用すると、ユーザーのデバイスは限られたアクセス トークンでストレージ サービスに直接、要求を実行できるようになります。 たとえば、ユーザーがアプリケーションに写真をアップロードする場合は、Web ロールが特定の BLOB またはコンテナーに対する書き込みアクセスを 30 分間だけ許可する SAS トークンを生成し、ユーザーのデバイスに送信します (30 分が経過すると、SAS トークンは期限切れになります)。

通常は、あるドメイン上の Web サイトにホストされているページで、他のドメインに対する "PUT" などの特別な操作を実行する JavaScript は許可されません。 たとえば、"contosomarketing.cloudapp.net" で Web ロールをホストしている場合に、クライアント側の JavaScript で BLOB を "contosoproducts.blob.core.windows.net" のストレージ アカウントにアップロードしようとすると、ブラウザーの "Same Origin Policy" によって操作が禁止されます。 CORS は、ソース ドメイン (この例では Web ロール) で生成された要求を信頼するようブラウザーに通知することを、ターゲット ドメイン (この例ではストレージ アカウント) に許可するブラウザー機能です。

どちらのテクノロジも、Web アプリケーションに不要な負荷 (およびボトルネック) をかけずに運用するために役立ちます。

有用な情報

SAS の詳細については、「 共有アクセス署名、パート 1:SAS モデルについて」を参照してください。

CORS の詳細については、「 Azure ストレージ サービスでのクロス オリジン リソース共有 (CORS) のサポート」を参照してください。

Caching (キャッシュ)

データの取得

一般に、1 つのサービスから 1 回でデータを取得する方が、2 回に分けて取得するよりも適切です。 Web ロールで実行している MVC Web アプリケーションが、ユーザー向けコンテンツとして、ストレージ サービスから 50 MB の BLOB を取得した例を考えてみます。 アプリケーションは、この後もユーザーから要求があるたびに同じ BLOB を取得するか、BLOB をローカル ディスクにキャッシュして、以降のユーザー要求に対し、繰り返し再使用することができます。 さらにユーザーがデータを要求すると、アプリケーションは更新時刻を記した条件付きヘッダーで GET を発行します。これによって、更新がない場合に BLOB 全体を取得しないように制御します。 これと同じパターンをテーブル エンティティの操作に適用できます。

場合によっては、アプリケーションが BLOB を取得した後、短い間だけその BLOB を有効と見なし、期間中は BLOB の更新を確認しないように設定してもかまいません。

アプリケーションが常に使用する構成や検索などのデータは、頻繁にキャッシュの対象とされます。

.NET を使用して BLOB のプロパティを取得し、最終更新日を確認する方法の例については、「 プロパティおよびメタデータの設定と取得」を参照してください。 条件付きダウンロードの詳細については、MSDN の「 BLOB サービス操作の条件ヘッダーの指定」を参照してください。

データの一括アップロード

一部のアプリケーション シナリオでは、データをローカルで集計し、それらをすぐ個別にアップロードするのではなく、定期的に一括でアップロードすることができます。 たとえば、Web アプリケーションがアクティビティのログ ファイルを保持する場合があります。つまり、アプリケーションはアクティビティが発生するたびに、それぞれの詳細をテーブル エンティティとしてアップロードできますが (多くのストレージ操作が必要)、ほかに、アクティビティの詳細をローカルのログ ファイルに保存し、それらの全詳細を区切り記号で区切って記録したファイルを定期的に BLOB にアップロードすることもできます。 各ログ エントリが 1 KB であれば、1 回の "Put Blob" トランザクションで何千個もアップロードできます (1 回のトランザクションで最大 64 MB の BLOB をアップロード可能)。 もちろん、アップロードする前にローカル マシンがクラッシュし、ログ データが失われる可能性もあります。アプリケーション開発者は、クライアント デバイスに障害が起きたり、アップロードに失敗したりする可能性を設計に組み込む必要があります。 単発のアクティビティではなく、複数の期間にわたってアクティビティ データをダウンロードする必要がある場合は、テーブルよりも BLOB をお勧めします。

.NET 構成

このセクションでは、.NET Framework を使用してパフォーマンスの大幅な向上を図る場合に利用できる簡単な構成を示します。 他の言語を使用する場合は、その言語に類似の概念がないか確認してください。

既定の接続数の上限を増加する

.NET の次のコードは、既定の接続数の上限 (通常、クライアント環境では 2、サーバー環境では 10) を 100 に増やします。 一般的に、この値はアプリケーションが使用するおおよそのスレッド数に設定します。

ServicePointManager.DefaultConnectionLimit = 100; //(Or More)  

接続数の上限は、接続を開始する前に設定する必要があります。

他のプログラミング言語については、対象の言語のドキュメントで接続数の上限の設定方法を参照してください。

詳細については、ブログの投稿「 Web Services: Concurrent Connections (Web サービス: 同時接続数)」を参照してください。

非同期タスクを伴う同期コードを使用する場合は、スレッド プールの最小スレッド数 (ThreadPool Min Threads) を増やす

このコードはスレッド プールの最小スレッド数を増やします:

ThreadPool.SetMinThreads(100,100); //(Determine the right number for your application)  

詳細については、「 ThreadPool.SetMinThreads メソッド」を参照してください。

.NET 4.5 のガベージ コレクションを活用する

クライアント アプリケーション用に .NET 4.5 以降を使用すると、サーバー ガベージ コレクションによるパフォーマンス向上が期待できます。

詳細については、記事「 .NET 4.5 におけるパフォーマンス向上の概要」を参照してください。

無制限の並列処理

並列処理はパフォーマンスにとって非常に有用ですが、複数のワーカーを使用して同じストレージ アカウント内の複数のパーティション (コンテナー、キュー、テーブル パーティション) にアクセスする状況や、同じパーティション内の複数の項目にアクセスする状況で、データのアップロードとダウンロードに無制限の並列処理 (スレッドや並列要求の数の上限なし) を使用する場合には、注意が必要です。 並列処理が無制限の場合、アプリケーションはクライアント デバイスの処理能力やストレージ アカウントのスケーラビリティ ターゲットを超過することがあり、その結果、遅延や調整時間が長くなります。

ストレージ クライアント ライブラリとツール

常に、Microsoft が提供する最新のクライアント ライブラリとツールを使用してください。 この記事の執筆時点では、.NET、Windows Phone、Windows Runtime、Java、および C++ 用のクライアント ライブラリを利用できます。他の言語のプレビュー版ライブラリも利用できます。 さらに、Microsoft は Azure Storage の操作用に、PowerShell コマンドレットと Azure CLI コマンドをリリースしています。 Microsoft はパフォーマンスに留意してこれらのツールを積極的に開発し、最新のサービス バージョンに遅れることなく対応して、数多くのパフォーマンスの実証済みプラクティスを内部で確実に処理できるように取り組んでいます。

再試行

調整とサーバー ビジー

ストレージ サービスは、アプリケーションを調整しているときや、なんらかの一時的な状態のために要求を処理できない場合に、"503 サーバーはビジー状態" や "500 操作タイムアウト" メッセージを返すことがあります。 こうしたメッセージは、アプリケーションがスケーラビリティ ターゲットに接近している場合や、システムがパーティション分割されたデータを再調整し、スループットの向上を試みている場合に表示されます。 通常、クライアント アプリケーションはエラーを引き起こしている操作を再試行します。後で同じ要求を送信すると、正常に処理されることもあります。 しかし、スケーラビリティ ターゲットを超過したアプリケーションをストレージ サービスが調整している場合や、他の理由でサービスが要求を処理できない場合に、積極的な再試行を実行すると、多くの場合は問題が悪化します。 したがって、再試行には指数関数的バックオフを使用してください (クライアント ライブラリはこの動作が既定)。 この動作では、たとえば、アプリケーションが再試行する間隔を、2 秒後、4 秒後、10 秒後、30 秒後と延ばしていき、最終的に再試行を取りやめます。 これにより、アプリケーションは問題を悪化させずに、サービスに対する負荷を大幅に軽減できます。

接続エラーは、調整の結果ではなく、一時的な問題と予想されるので、直後に再試行を実行してかまいません。

再試行できないエラー

クライアント ライブラリは、再試行できるエラーとできないエラーを区別します。 しかし、ストレージ REST API に対して独自のコードを記述する場合は、一部のエラーでは再試行を実施しないでください。たとえば、400 (正しくない要求) 応答は、クライアント アプリケーションが想定されていない形式で要求を送信したため、処理できなかったという事態を示します。 この要求を再送信しても、毎回同じ応答が返されることになるので、再試行は無意味です。 ストレージ REST API に対して独自のコードを記述する場合は、エラー コードの示す内容と各エラーに対する適切な再試行の方法 (または可否) を理解する必要があります。

有用な情報

ストレージのエラー コードの詳細については、Microsoft Azure Web サイトの「 ステータス コードとエラー コード 」を参照してください。

BLOB

既に説明した すべてのサービス 向けの実証済みプラクティスに加えて、ここでは、BLOB サービスに適用する実証済みプラクティスについて説明します。

BLOB 固有のスケーラビリティ ターゲット

1 つのオブジェクトに同時にアクセスする複数のクライアント

1 つのオブジェクトに多数のクライアントが同時にアクセスする場合は、オブジェクトごとおよびストレージ アカウントごとにスケーラビリティ ターゲットを考慮する必要があります。 1 つのオブジェクトにアクセスできるクライアントの正確な数は、オブジェクトを同時に要求するクライアントの数、オブジェクトのサイズ、ネットワークの状態などの要因によって異なります。

Web サイトから提供されるイメージやビデオなどのように CDN によってオブジェクトを配信できる場合は、CDN を使用する必要があります。 こちらを参照してください。

データが機密である科学シミュレーションなどの他のシナリオでは、2 つのオプションがあります。 第 1 のオプションは、同時にアクセスするのではなく、オブジェクトに一定の時間アクセスするようにワークロードのアクセスを調整します。 または、複数のストレージ アカウントにオブジェクトを一時的にコピーし、オブジェクトごとおよびストレージ アカウント全体の合計 IOPS を高くします。 限定的なテストでは、約 25 個の VM が同時に 100 GB の BLOB を並列でダウンロードできました (各 VM は 32 個のスレッドを使ってダウンロードを並列化しました)。 100 個のクライアントがオブジェクトにアクセスする必要がある場合は、最初にオブジェクトを第 2 のストレージ アカウントにコピーした後、最初の 50 個の VM は第 1 の BLOB にアクセスし、残りの 50 個の VM は第 2 の BLOB にアクセスします。 結果はアプリケーションの動作によって大きく異なるので、設計時にテストする必要があります。

BLOB ごとの帯域幅と操作

1 つの BLOB に対して、最大で 60 MB/秒の読み取りまたは書き込みを実行できます (これは約 480 Mbps に相当し、クライアント デバイスの物理 NIC をはじめ、多くのクライアント側ネットワークの処理能力を超えています)。 さらに、1 つの BLOB は 1 秒あたり最大 500 要求をサポートします。 複数のクライアントが同じ BLOB を読み取る必要があり、これらの制限を超過する場合は、CDN を使用した BLOB 配信を検討してください。

BLOB のターゲット スループットの詳細については、「 Azure Storage のスケーラビリティおよびパフォーマンスのターゲット」を参照してください。

BLOB のコピーと移動

BLOB のコピー

ストレージ REST API Version 2012-02-12 は、複数のアカウント間で BLOB のコピーを実行する有用な機能を実装しました。クライアント アプリケーションはストレージ サービスに対して、他のソース (別のストレージ アカウントも可能) から BLOB をコピーするよう指示を出し、そのサービスに非同期でコピーを実行させることができます。 これによってデータのダウンロードとアップロードが不要になるため、他のストレージ アカウントからデータを移行するときにアプリケーションが必要とする帯域幅を大幅に削減できます。

ただし、ストレージ アカウント間でコピーを実行する場合は、コピーの完了時間に関する保証は得られません。 アプリケーションで BLOB のコピーを適宜、迅速に完了する必要がある場合は、VM に BLOB をダウンロードしてから、目的の場所にアップロードする方法でコピーを実行してください。 この状況で確実な予測を行うには、同一の Azure リージョンで実行している VM でコピーを実行します。そうしない場合は、ネットワークの状態により、コピーのパフォーマンスに (高い確率で) 影響が生じます。 加えて、プログラムにより非同期コピーの進捗を監視できます。

通常、同一のストレージ アカウント内でのコピーは、すばやく完了します。

詳細については、「 Copy Blob」を参照してください。

AzCopy の使用

Azure Storage チームは、ストレージ アカウントとの間やストレージ アカウント間で多数の BLOB を一括転送できる、"AzCopy" コマンド ライン ツールをリリースしました。 このツールは、そうしたシナリオに最適であり、高い転送速度を実現できます。 アップロードやダウンロード、コピーを一括で実行するシナリオに使用してください。 詳細情報とダウンロード方法については、「 AzCopy コマンドライン ユーティリティを使用してデータを転送する」を参照してください。

Azure のインポート/エクスポート サービス

非常に大量のデータ (1 TB 超) を対象に、Azure Storage はインポート/エクスポート サービスを提供しています。このサービスでは、ハード ドライブを発送して、BLOB ストレージへのアップロードや BLOB ストレージからのダウンロードを実施できます。 アップロードの場合は、ハード ドライブにデータを格納して Microsoft に発送し、ダウンロードの場合は、空のハード ドライブを Microsoft に発送します。 詳しくは、「Microsoft Azure Import/Export サービスを使用した BLOB ストレージへのデータの転送」をご覧ください。 非常に大量のデータのアップロードやダウンロードは、ネットワークを介して実施するよりも、このサービスの方がはるかに効率的です。

メタデータの使用

BLOB サービスは HEAD 要求をサポートしており、BLOB に関するメタデータを含めることができます。 たとえば、アプリケーションは写真の EXIF データを必要とする場合に、写真を取得してデータを抽出できます。 帯域幅の節約とパフォーマンスの向上を目的として、アプリケーションは写真をアップロードする場合、BLOB のメタデータに EXIF データを保存できます。これ以降は HEAD 要求だけを使用してメタデータの EXIF データを取得できるため、BLOB を読み取るたびに EXIF データを抽出するのに必要な、帯域幅と処理時間の大幅な削減につながります。 この方法は、BLOB のコンテンツ全体ではなくメタデータだけが必要な場合に役立ちます。 1 つの BLOB に格納できるメタデータはわずか 8 KB であり、これを超えるメタデータを格納する要求はサービスに拒否されるため、データのサイズが適合しない場合は、この方法は使用できません。

.NET を使用して BLOB のメタデータを取得する方法の例については、「 プロパティおよびメタデータの設定と取得」を参照してください。

迅速なアップロード

BLOB を迅速にアップロードするには、まず、アップロードする BLOB は 1 つか、それとも複数かということを考えます。 以下のガイダンスを参考に、状況に応じて、適切な方法を見つけてください。

1 つの大きな BLOB を迅速にアップロードする

1 つの大きな BLOB を迅速にアップロードするには、クライアント アプリケーションがブロックやページを並列アップロードする必要があります (個々の BLOB とストレージ アカウント全体に関するスケーラビリティ ターゲットに注意してください)。 Microsoft が提供する公式の RTM ストレージ クライアント ライブラリ (.NET、Java) で、このアップロードを実行できます。 ライブラリごとに指定されている以下のオブジェクトまたはプロパティを使用して、同時実行のレベルを設定します。

  • .NET: BlobRequestOptions オブジェクトで ParallelOperationThreadCount の使用を設定します。
  • Java/Android: BlobRequestOptions.setConcurrentRequestCount() を使用します。
  • Node.js: 要求オプションまたは BLOB サービスのいずれかで、parallelOperationThreadCount を使用します。
  • C++: blob_request_options::set_parallelism_factor メソッドを使用します。

多数の BLOB をすばやくアップロードする

多数の BLOB をすばやくアップロードするには、複数の BLOB を並列アップロードします。 この方法は、ストレージ サービスの複数のパーティションにわたってアップロードを展開するため、ブロックの並列アップロードで一度に 1 つの BLOB をアップロードする方法よりも高速です。 1 つの BLOB は 60 MB/秒のスループット (約 480 Mbps) のみをサポートします。 この記事の執筆時点で、US ベースの LRS アカウントは、個々の BLOB が対応しているスループットを大きく上回る最大 20 Gbps の受信をサポートしています。 AzCopy は既定で並列アップロードを実行するため、このシナリオ用にお勧めします。

正しい種類の BLOB の選択

Azure Storage がサポートしている BLOB には、ページ BLOB とブロック BLOB の 2 種類があります。 特定の使用シナリオでは、BLOB の種類の選択がソリューションのパフォーマンスとスケーラビリティに影響を及ぼします。 ブロック blob は大量のデータを効率的にアップロードする場合に適しています。たとえば、クライアント アプリケーションが BLOB ストレージに写真やビデオをアップロードする必要がある場合です。 ページ blob はアプリケーションがランダム書き込みを実行する必要がある場合に適しています。たとえば、Azure VHD がページ blob として格納されている場合です。

詳細については、「 ブロック BLOB、追加 BLOB、ページ BLOB について」を参照してください。

テーブル

既に説明した すべてのサービス 向けの実証済みプラクティスに加えて、ここでは、テーブル サービスに適用する実証済みプラクティスについて説明します。

テーブル固有のスケーラビリティ ターゲット

ストレージ アカウント全体の帯域幅制限に加えて、テーブルにも以下のような固有のスケーラビリティ限界が存在します。 トラフィックが増大するとシステムが負荷分散を実行しますが、トラフィックの急増直後には、対象ボリュームのスループットが得られない場合もあります。 使用しているパターンで急増が起きた場合は、ストレージ サービスが自動でテーブルの負荷分散を実行するため、その間に調整やタイムアウトが発生することを想定しておく必要があります。 負荷が緩やかに増加した場合は、システムが適切に負荷分散を実行する時間が確保できるため、一般的によい結果が得られます。

1 秒あたりのエンティティ (アカウント)

テーブルに対するアクセスのスケーラビリティ限界は、1 アカウントにつき 1 秒あたり最大 20,000 エンティティ (各 1 KB) です。 一般に、挿入、更新、削除、スキャンされたエンティティがそれぞれ、このターゲットに対してカウントされます。 したがって、100 エンティティを含むバッチ挿入は 100 エンティティとカウントされます。 1 回のクエリで 1,000 エンティティをスキャンし、5 つが返された場合のカウントは、1,000 エンティティです。

1 秒あたりのエンティティ (パーティション)

単一パーティション内のテーブルに対するアクセスのスケーラビリティ ターゲットは、1 秒あたり 2,000 エンティティ (各 1 KB) です。カウント方法は前のセクションと同じです。

構成

このセクションでは、テーブル サービスのパフォーマンスを大幅に向上させるための簡単な構成を示します。

JSON の使用

ストレージ サービス Version 2013-08-15 より、テーブル サービスでは、テーブル データの転送用に、XML ベースの AtomPub 形式に代えて JSON を使用できるようになりました。 これにより、ペイロード サイズが 75% 程度に抑えられ、アプリケーションのパフォーマンスを大幅に引き上げることができます。

詳しくは、投稿「Microsoft Azure Tables: Introducing JSON (Microsoft Azure テーブル: JSON の紹介)」と、「テーブル サービス操作のペイロード形式」をご覧ください。

Nagle のオフ

Nagle のアルゴリズムは、ネットワーク パフォーマンスを向上させる方法として、TCP/IP ネットワークで広く使用されています。 しかし、すべての状況に適しているわけではありません (高度な対話形式の環境などには不向き)。 Azure Storage では、Nagle のアルゴリズムがテーブル サービスやキュー サービスに対する要求のパフォーマンスにマイナスの影響を及ぼすため、可能な場合は無効にしてください。

詳しくは、ブログ記事「Nagle's Algorithm is Not Friendly towards Small Requests (Nagle のアルゴリズムは小さな要求に不親切)」をご覧ください。この記事では、Nagle アルゴリズムがテーブルやキューの要求に十分対応できない理由を説明し、クライアント アプリケーションでこのアルゴリズムを無効にする方法を示しています。

スキーマ

データの表現とクエリの方法は、テーブル サービスのパフォーマンスに影響を及ぼす単一要因として最大のものです。 アプリケーションごとに違いはありますが、このセクションでは、以下に関連する一般的な実証済みプラクティスの概略を示します。

  • テーブル設計
  • 効率的なクエリ
  • 効率的なデータ更新

テーブルとパーティション

テーブルはパーティションに分割されます。 同じパーティションに格納されるエンティティは、いずれも同じパーティション キーを共有し、一意の行キーによってパーティション内で識別されます。 パーティションには利点もありますが、スケーラビリティ限界ももたらします。

  • 利点: 最大 100 個のストレージ操作 (総サイズの上限は 4 MB) を含む単一のアトミック バッチ トランザクションで、同じパーティション内のエンティティを更新できます。 また、取得するエンティティが同数であれば、複数のパーティションにまたがるデータのクエリよりも、単一パーティションに含まれるデータのクエリの方が効率的に実行できます (ただし、テーブル データのクエリに関する推奨事項を参照してください)。
  • スケーラビリティ限界: パーティションはアトミック バッチ トランザクションをサポートしているため、単一パーティションに格納されているエンティティへのアクセスは、負荷分散の対象になりません。 したがって、個々のテーブル パーティションのスケーラビリティ ターゲットは、テーブル サービス全体のターゲットよりも低くなります。

テーブルとパーティションにはこうした特徴があるため、以下の設計原理を適用します。

  • クライアント アプリケーションが作業の同一論理単位内で頻繁に更新やクエリを実行するデータは、同じパーティションに配置します。 この配置をとる理由は、アプリケーションによって書き込みが集約されることであり、また、アトミック バッチ操作の利点を活かすためでもあります。 さらに、単一パーティションに含まれるデータは、複数のパーティションにまたがるデータよりも 1 回で効率的にクエリを実行できます。
  • クライアント アプリケーションが作業 (単一クエリまたはバッチ更新) の同一論理単位内で挿入や更新、クエリを実行しないデータは、別のパーティションに配置します。 ここで重要なのは、単一テーブル内のパーティション キーの数には上限がないということです。そのため、パーティション キーが数百万個あっても問題にはならず、パフォーマンスは影響を受けません。 たとえばアプリケーションが、ユーザー ログインが必要でアクセス数の多い Web サイトである場合、パーティション キーとして User Id を使用することは適切です。

ホット パーティション

"ホット パーティション" とは、1 つのアカウントに対するトラフィックのうち、突出して大きな割合の通信が行われていながら、それが単一のパーティションであるために負荷分散を実行できないパーティションです。 一般的にホット パーティションは、次の 2 つのうち、いずれかの状況で発生します。

末尾または先頭にのみ追加されるパターン

"追加のみ" パターンでは、特定の PK に対するすべての (または、ほとんどすべての) トラフィックが現在時刻によって増減します。 たとえば、アプリケーションがログ データのパーティション キーとして現在日時を使用するケースです。 この場合は、すべての挿入がテーブルの最後のパーティションに対して実行され、あらゆる書き込みはテーブルの末尾に追加されることになるため、システムは負荷分散を実行できません。 対象のパーティションに対するトラフィックの量がパーティション レベルのスケーラビリティ ターゲットを超えると、システムは調整を開始します。 トラフィックを複数のパーティションに送り、要求の負荷をテーブル全体に分散することが必要です。

大量のトラフィック データ

採用したパーティショニング スキームにより、あるパーティションのデータが別のパーティションよりもはるかに多く使用される事態が生じると、その単一パーティションのトラフィックがスケーラビリティ ターゲットに接近し、調整が実行されることがあります。 いずれのパーティションもスケーラビリティ ターゲットに達しないように、パーティション スキームを確認してください。

クエリ実行

このセクションでは、テーブル サービスのクエリに関する実証済みプラクティスについて説明します。

クエリ スコープ

複数の方法で、クエリで照会するエンティティの範囲を指定できます。 以下では、各方法の使用について説明します。

通常はスキャン (単一のエンティティを超える大きさのクエリ) を実行しないようにしますが、避けられない場合は、必要のない大量のエンティティをスキャンしたり返したりせずに目的のデータを取得できるようデータを編成してみてください。

ポイント クエリ

ポイント クエリは 1 つのエンティティを正確に取得します。 取得するエンティティのパーティション キーと行キーの両方を指定して実行します。 このクエリは非常に効率的であるため、可能であれば常にこれを使用してください。

パーティション クエリ

パーティション クエリは、共通のパーティション キーを持つデータのセットを取得するクエリです。 通常このクエリでは、パーティション キーに加えて、行キー値の範囲かいくつかのエンティティ プロパティ値の範囲を指定します。 これらは、ポイント クエリより低効率であるため、多用しないでください。

テーブル クエリ

テーブル クエリは、共通のパーティション キーを持たないエンティティのセットを取得するクエリです。 このクエリは効率的でないため、可能であれば使用を控えてください。

クエリ密度

クエリ効率に関する他の主要な要因は、結果のセットを特定するためのスキャンが行われたエンティティの数に対する、返されたエンティティの数です。 1% のデータだけに共通するプロパティ値に適合するフィルターと共にテーブル クエリを実行すると、このクエリは 1 つのエンティティを返すごとに 100 エンティティをスキャンすることになります。 前に説明したテーブルのスケーラビリティ ターゲットはいずれも、返されるエンティティ数ではなく、スキャンを実行するエンティティ数に関係しています。つまり、クエリ密度が低いと、目的のエンティティを取得するために非常に多くのエンティティをスキャンしなければならないため、テーブル サービスによるアプリケーションの調整が発生しやすくなります。 これを回避する方法の詳細については、後の「非正規化」セクションをご覧ください。

必要なデータ量の制限
フィルター処理

クエリによって、クライアント アプリケーションにとって不要なエンティティが返される場合は、フィルターを使用して結果のサイズを減らすことを検討してください。 クライアントに返されないエンティティもスケーラビリティ限界に対してカウントされますが、ネットワーク ペイロードのサイズが小さくなり、クライアント アプリケーションが処理しなければならないエンティティの数も少なくなるため、アプリケーションのパフォーマンスは向上します。 前の「クエリ密度」の説明をご覧ください。ただし、スケーラビリティ ターゲットはスキャンされるエンティティ数に関連するため、多くのエンティティを除外するクエリは、ほとんどエンティティを返さない場合でも、調整を引き起こすことがあります。

プロジェクション

クライアント アプリケーションが、テーブルに含まれるエンティティのプロパティのごく一部しか必要としない場合は、プロジェクションを使用して、返されるデータ セットのサイズを制限できます。 フィルター処理と同じく、この方法はネットワークの負荷とクライアントによる処理の削減に役立ちます。

非正規化

リレーショナル データベースを運用する場合とは異なり、テーブル データに対する効率的なクエリの実証済みプラクティスは、データを非正規化することにつながります。 つまり、多数のエンティティをスキャンしてアプリケーションに必要なデータを見つけるのではなく、複数のエンティティで同じデータを (データの検索に使用するキーごとに 1 つ) 複製し、クライアントに必要なデータを探すためにクエリでスキャンしなければならないエンティティ数を最小にします。 たとえば電子商取引を行う Web サイトでは、ある注文を見つけるために、カスタマー ID (特定の顧客の注文を探す) と日付 (特定の日の注文を探す) の両方での検索が必要になることがあります。 テーブル ストレージでの最適な方法は、エンティティ (またはエンティティに対する参照) を 2 回格納することです。1 回はカスタマー ID で検索しやすくするためにテーブル名、PK、RK と共に格納し、もう 1 回は日付で検索しやすくするために行います。

挿入/更新/削除

このセクションでは、テーブル サービスに格納されているエンティティの変更に関する実証済みプラクティスについて説明します。

バッチ処理

Azure Storage では、バッチ トランザクションはエンティティ グループ トランザクション (ETG) と呼ばれています。ETG に含まれるすべての操作は、単一テーブル内の 1 つのパーティションで実行されます。 可能な場合は、ETG を使用して一括での挿入、更新、削除を実行してください。 これにより、クライアント アプリケーションとサーバー間のラウンド トリップ数が減少し、課金対象のトランザクション数も少なくなります (1 つの ETG は課金対象の 1 回のトランザクションとしてカウントされ、最大 100 回のストレージ操作が含まれます)。さらに、アトミックな更新 (1 回の ETG ですべての操作が成功するか、すべて失敗するかのいずれか) も可能になります。 モバイル デバイスなどの待機時間が長い環境では、ETG を使用することで大きなメリットが得られます。

アップサート (Upsert)

可能な場合は、常にテーブルの アップサート 操作を使用します。 アップサートには 2 種類あり、いずれも従来の挿入操作と更新操作に比べて効率的です。

  • InsertOrMerge: エンティティ プロパティのサブセットをアップロードする必要があるものの、エンティティが既に存在するかどうかが明らかでない場合に使います。 エンティティが存在する場合、この呼び出しはアップサート操作に含まれるプロパティを更新し、既存のプロパティはすべてそのまま残します。エンティティが存在しない場合は、新しいエンティティを挿入します。 変更するプロパティのアップロードだけが必要とされる点が、クエリにおけるプロジェクションの使用に類似しています。
  • InsertOrReplace: 新しいエンティティをアップロードする必要があるものの、エンティティが既に存在するかどうかが明らかでない場合に使用します。 この方法は、以前のエンティティを全面的に上書きするため、新たにアップロードするエンティティに誤りが無いことが確実な場合にのみ使用してください。 たとえば、アプリケーションが以前にユーザーの場所データを保存しているかどうかにかかわらず、ユーザーの現在の場所を格納しているエンティティを更新する必要があり、その新しい場所エンティティに問題がなく、かつ以前のすべてのエンティティが持つあらゆる情報を必要としない場合などです。
単一エンティティでのデータ シリーズの格納

アプリケーションが、頻繁にすべてを一括で取得しなければならない一連のデータを保存する場合があります。たとえば、アプリケーションが直近 24 時間のデータを反映するチャートをプロットするために、時間の経過に伴う CPU 使用率を追跡している場合です。 このとき、正時ごとに対応するテーブル エンティティを 1 つずつ作成し、各エンティティに特定の時刻の CPU 使用率を格納する方法をとることができます。 このデータをプロットするには、アプリケーションが直近 24 時間のデータを保持しているエンティティを取得する必要があります。

また、別の方法として、アプリケーションが各時刻の CPU 使用率を単一エンティティの個々のプロパティとして格納することもできます。アプリケーションは InsertOrMerge Upsert の呼び出しを実行するたびに直近の時刻の値を更新でき、その値を毎時間の更新に使うことができます。 データをプロットするためにアプリケーションが取得するエンティティは、24 個ではなく 1 つだけであるため、非常に効率的なクエリを実行できます (前の「クエリ スコープ」の説明を参照)。

BLOB での構造化データの格納

構造化データはテーブルに格納するデータのように考えられる場合もありますが、常にいくつかのエンティティ範囲がまとめて取得され、それらをバッチ挿入することができます。 典型的な例はログ ファイルです。 この例では、数分間のログを一括で処理して挿入を実行することができ、そのときに、ユーザーは必ず数分間のログを一度に取得します。 この場合は、テーブルではなく BLOB を使用した方が、書き込まれるオブジェクトと返されるオブジェクトの数を大幅に削減でき、さらに通常は必要な要求数も減らすことができるため、パフォーマンスの面で優れています。

キュー

既に説明したすべてのサービス向けの実証済みプラクティスに加えて、ここでは、キュー サービスに適用する実証済みプラクティスについて説明します。

スケーラビリティ限界

1 つのキューは、1 秒あたり約 2,000 メッセージ (各 1 KB) を処理できます (ここでは各 AddMessage、GetMessage、 DeleteMessage を 1 つのメッセージとカウントします)。 これがアプリケーションにとって十分でない場合は、複数のキューを使用してメッセージを分散する必要があります。

Azure Storage のスケーラビリティおよびパフォーマンスのターゲット」で、現在のスケーラビリティ ターゲットを確認してください。

Nagle のオフ

Nagle アルゴリズムについて論じているテーブル構成のセクションを参照してください。Nagle アルゴリズムは、一般的にキュー要求のパフォーマンスに適していないため、無効にする必要があります。

メッセージ サイズ

メッセージ サイズが増加すると、キューのパフォーマンスとスケーラビリティが低下します。 メッセージには、受信者が必要な情報のみを含める必要があります。

一括取得

1 回の操作でキューから最大 32 個のメッセージを取得できます。 これにより、クライアント アプリケーションの取得回数を減らすことができ、モバイル デバイスなどの待機時間が長い環境では特に役立ちます。

キューのポーリング間隔

多くのアプリケーションはキューからメッセージをポーリングします。キューは、そのアプリケーションにとって最大のトランザクション ソースの 1 つです。 ポーリング間隔を適切に選択します。ポーリング頻度が高すぎると、アプリケーションはキューのスケーラビリティ ターゲットに近づく可能性があります。 ただし、200,000 トランザクションあたり 0.01 ドル (記事の執筆時点) で、1 つのプロセッサが 1 か月間 1 秒に 1 回ポーリングする場合、そのコストは 15 セントにも満たないため、通常、コストはポーリング間隔の選択に影響を与える要因ではありません。

最新のコストの情報については、「 Azure Storage 料金」をご覧ください。

UpdateMessage

UpdateMessage を使用すると、非常時タイムアウトを長くしたり、メッセージの状態情報を更新したりすることができます。 この機能は効果的ですが、各 UpdateMessage 操作はスケーラビリティ ターゲットにカウントされることに留意してください。 しかし、それでもジョブの手順が完了するごとに、次のキューにジョブを渡すワークフローに比べると、はるかに効率的な方法です。 UpdateMessage 操作を使用すると、アプリケーションは、ジョブの各手順が完了するたびに次の手順に関するメッセージをキューから取得するのではなく、ジョブ状態をメッセージに保存して、処理を継続できるようになります。

詳細については、「 方法: キューに配置されたメッセージの内容を変更する」を参照してください。

アプリケーションのアーキテクチャ

アプリケーション アーキテクチャの拡張性を確保するには、キューを使用します。 以下のリストは、キューを使用して、アプリケーションの拡張性を高めるための方法を示しています。

  • キューを使用して、処理に関する作業のバックログを作成し、アプリケーションのワークロードを平滑化するために利用できます。 たとえば、アップロード済み画像のサイズ変更など、プロセッサの負荷が高い作業の要求をキューに残しておくことができます。
  • キューを使用して、アプリケーションの一部を切り離し、個別に拡張することができます。 たとえば、Web フロントエンドがユーザーから得られた調査結果をキューに配置し、将来の解析とストレージに活用できます。 必要に応じて、キュー データを処理する worker ロール インスタンスを追加できます。

まとめ

この記事では、Azure Storage 使用時のパフォーマンスを最適化する実証済みプラクティスのうち、よく用いられるものをいくつか取り上げました。 すべてのアプリケーション開発者に対して、この記事で示した個々のプラクティスに照らしてアプリケーションを評価し、推奨事項に基づく動作によって、Azure Storage を使用するアプリケーションが優れたパフォーマンスを発揮できるように検討することをお勧めします。