Azure VM でのSQL Serverへの適用
この記事では、SQL Server on Azure Virtual Machines (VM) の I/O パフォーマンスを分析して、仮想マシンとデータ ディスクの制限を超えた結果として発生する問題を見つける方法について説明します。
Overview
SQL Serverパフォーマンスの問題のトラブルシューティングにはさまざまなツールが役立ちますが、Azure VM で効果的に行うには、ホスト レベルとSQL Server インスタンスの両方で何が起こっているかを理解することが重要です。多くの場合、ホスト メトリックと SQL Server ワークロードの関連付けが困難な場合があります。 Azure VM でSQL Serverすると、IOPS (1 秒あたりの入力/出力) や、仮想マシンとデータ ディスクの制限を超えた場合のスループット調整に起因するパフォーマンスの問題を簡単に特定できます。
問題を示すパフォーマンス メトリックと、それに対処するための潜在的な手順は、Azure ポータルで入手でき、Azure CLIでクエリを実行できます。
Azure ポータルの StorageSQL 仮想マシン リソースのウィンドウは、次の作業を支援します。
- ストレージ構成を管理する
- I/O 調整を識別する
- I/O 関連のベスト プラクティスについてシステムを評価する
指標の理解
[I/O 分析] タブでは、Azure メトリックを使用してディスクの待機時間と、VM またはディスク I/O 調整を識別します。 Azureメトリックは 30 秒ごとにサンプリングされ、1 分ごとに集計されます。
システムは、調整とディスク待機時間を監視します。 一部の調整は想定されており、ディスクの待ち時間がない限り無視されます。 連続する 5 分間に 500 ミリ秒を超えるディスク待ち時間が発生した場合、システムは次の処理を行います。
- パフォーマンス メトリックをさらに詳しく調べる
- 調整されたリソースを識別する
- 考えられる根本原因と軽減手順を提供する
次の表では、問題のある調整の問題を特定するために使用されるAzure メトリックについて説明します。
| Azure メトリック | メトリックの説明 | 原因となっている状態 | I/O 調整の結論 |
|---|---|---|---|
| ディスク待機時間 (プレビュー) | 監視期間中のデータ ディスクの IO を完了するための平均時間。 値はミリ秒単位で示されます。 | >連続する 5 分間で 500 ミリ秒 | システムが潜在的な調整をさらに調査するための待ち時間の問題があります。 |
| キャッシュされた VM IOPS の消費率 | 仮想マシンのキャッシュあり IOPS の上限に対する完了済みの合計 IOPS で計算された割合。 | >= 連続する 5 分間で 95% | VM の調整があります。 SQL 仮想マシンで実行されているアプリケーションは、仮想マシンで使用可能な最大キャッシュ IOPS 容量をすべて利用しています。アプリケーションのストレージ要求が、仮想マシンの基になるストレージ構成によって提供されるキャッシュされた IOPS を超えています。 |
| VM のキャッシュされた帯域幅の消費率 | 仮想マシンのキャッシュあり最大スループットに対する完了済みの合計ディスク スループットで計算された割合。 | >= 連続する 5 分間で 95% | VM の調整があります。 SQL 仮想マシンで実行されているアプリケーションは、データ転送に使用可能なキャッシュされたディスク帯域幅の最大値を利用しています。アプリケーションのデータ転送要求が、仮想マシンの基になるストレージ構成によって提供されるキャッシュされた帯域幅リソースを超えています。 |
| VM のキャッシュされていない IOPS の消費率 | 仮想マシンのキャッシュなし IOPS の上限に対する仮想マシンの完了済みの合計 IOPS で計算された割合。 | >= 連続する 5 分間で 95% | VM の調整があります。 SQL 仮想マシンで実行されているアプリケーションは、仮想マシンで使用可能なキャッシュされていない最大 IOPS 容量を利用しています。アプリケーションのストレージ要求が、仮想マシンの基になるストレージ構成によって提供されるキャッシュされていない IOPS リソースを超えています。 |
| VM のキャッシュされていない帯域幅の消費率 | 仮想マシンのプロビジョニングされた最大スループットに対する仮想マシンの完了済みの合計ディスク スループットで計算された割合。 | >= 連続する 5 分間で 95% | VM の調整があります。 SQL 仮想マシンで実行されているアプリケーションは、データ転送に許容されるキャッシュされていないディスク帯域幅の最大値を利用しています。アプリケーションのデータ転送要求が、仮想マシンの基になるストレージ構成によって提供されるキャッシュされていない帯域幅リソースを超えています。 |
| データ ディスク IOPS の消費率 | プロビジョニングされたデータ ディスク IOPS に対する完了済みのデータ ディスク IOPS で計算された割合。 | >= 連続する 5 分間で 95% | データ ディスクの調整があります。 SQL 仮想マシンで実行されているアプリケーションが、プロビジョニングされたデータ ディスクの IOPS 制限に達しています。アプリケーションのストレージ要求が、選択したディスク構成のパフォーマンス機能を超えています。 |
| データ ディスク帯域幅の消費率 | プロビジョニングされたデータ ディスクのスループットに対する完了済みのデータ ディスクのスループットで計算された割合。 | >= 連続する 5 分間で 95% | データ ディスクの調整があります。 SQL 仮想マシンで実行されているアプリケーションが、プロビジョニングされたデータ ディスクの IOPS 制限に達しています。アプリケーションのストレージ要求が、選択したディスク構成のパフォーマンス機能を超えています。 |
I/O解析の結果
過去 24 時間のパフォーマンス メトリックの分析に基づいて、I/O 分析では次のことが判断されます。
- 調整なし
- VM レベルの I/O 調整
- ディスク レベルの I/O 調整
I/Oスロットリングの問題はありません
パフォーマンスの問題が発生してもディスクの待機時間がない場合、パフォーマンスの問題は I/O 調整の問題が原因ではありません。 他の領域を調査する必要があります。 Azure VM でのSQL Serverに関するベスト プラクティス チェックリストを使用して、システムが効率的に構成されていることを確認したり、パフォーマンスSQL Serverに役立つリンクを見つけたりすることができます。 SQL のベスト プラクティス評価 機能を有効にすると、SQL Server VM の推奨事項の完全な一覧が表示されます。
VMレベルのI/Oスロットリング問題
Azure 仮想マシンは、さまざまなワークロードのさまざまなシリーズとサイズで提供されるクラウドベースのコンピューティング リソースであり、それぞれ異なる機能とパフォーマンス特性を備えています。 SQL Server ワークロードの場合、一般に、SQL Server ワークロードに推奨されるシリーズは、Ebdsv5、M、Mv2 シリーズなどのメモリ最適化されたシリーズです。
VM のサイズによって、SQL Server インスタンスで使用可能な vCPU、メモリ、ストレージの数が決まります。 ストレージと比べると、お客様が仮想マシンのサイズを変更し、アプリケーション リソースのニーズに基づいて VM をスケールアップおよびスケールダウンすることは比較的簡単です。 IOPS とスループットが VM レベルで調整される可能性があるため、パフォーマンスのニーズとワークロードのコストに基づいて適切な VM サイズを選択します。
Azureに移行する場合は、migration 適合性評価を使用して、現在のSQL Serverの構成と使用状況を分析し、Azureのワークロードに最適な VM サイズを提案できます。
次のAzureメトリックは、VM によって課される制限を超えないようにワークロードが調整されていることを判断するために使用されます。
- VM のキャッシュあり IOPS の消費率
- VM キャッシュ帯域幅の消費割合
- VM のキャッシュなし IOPS の消費率
- VM のキャッシュされていない帯域幅の消費率
VM の調整に関する重要なポイントを次に示します。
- VM シリーズ内の仮想マシンのサイズを変更することで、メモリ、仮想コア、スループット、IOPS を増やすことができます。
- データ ディスクの数がターゲット VM サイズの最大データ ディスク制限を超えるほど VM サイズを減らすことはできません。
- 調整パターンを決定することが重要です。 たとえば、ワークロードのチューニングによって調整の急増が頻繁に発生する可能性があります。一方、持続的なスパイクは、基になるストレージがワークロードを処理できないことを示している可能性があります。
ディスクレベルのI/Oスロットリング問題
SQL 仮想マシンのお客様にとって、ストレージの調整は仮想マシンのサイズを変更するよりも難しいため、ストレージは最適化されたパフォーマンスのために適切に構成する最も重要な側面です。 たとえば、Premium SSD の IOPS またはスループットを向上させるために変更を加える場合は、新しい記憶域プールを作成する必要があります。 そのため、デプロイ後のパフォーマンスの問題を回避するために、計画フェーズ中に価格とパフォーマンスの両方のためにストレージ構成を最適化することが重要です。
次のAzureメトリックは、ディスクによって設定された制限を超えたためにワークロードが制限されていることを判断するために使用されます。
- データ ディスク IOPS の消費率
- データ ディスク帯域幅の消費率
ディスク レベルの I/O 調整に関する次の重要なポイントを考慮してください。
- データ ディスクは、SQL Serverパフォーマンスにとって非常に重要です。 SQL Serverデータ (.mdf) ファイルとログ (.df) ファイルをデータ ディスクに配置することをお勧めします。
- データ ディスク レベルで調整を行う場合は、読み取りキャッシュを有効にします (使用可能な場合)。
データ ディスク IOPS の消費率
データ ディスクの IOPS 消費率 メトリックは、ディスク レベルでの IOPS 消費量を測定します。 一般に、高 IOPS のニーズは、高トランザクションの OLTP ベースのアプリケーションとワークロードに関連付けられています。
次のシナリオまたは条件は、データ ディスクの IOPS の制限を超える可能性があります。
- 高トランザクション ワークロード (IOPS): アプリケーションが頻繁に読み取りと書き込みの操作を伴う大量のデータベース トランザクションを処理している場合、割り当てられた IOPS をすぐに消費する可能性があります。
- 非効率的なクエリ: SQL クエリまたはデータ取得操作が最適化されていないと、I/O アクティビティが過剰になり、予想よりも多くの IOPS が消費される可能性があります。
- 同時ユーザー: 複数のユーザーまたはセッションが同時にデータベースにアクセスし、I/O 要求を生成している場合、累積効果によって IOPS の制限に達する可能性があります。
- 競合リソース:基盤となる物理インフラが他のテナントやワークロードと大きく共有されている場合、仮想マシンの利用可能なIOPSに影響を及ぼす可能性があります。
- 一時的なスパイク: バッチ処理やデータ移行などのワークロードの一時的な急増により、割り当てられた IOPS を超える I/O 需要が急激に増加する可能性があります。
- 小さいディスク サイズ: プロビジョニングされたデータ ディスク サイズが比較的小さい場合、IOPS 容量が制限される可能性があります。 個々の小さいディスクの IOPS 制限は低く、アプリケーションの要求がこの制限を超えると、"Data Disk IOPS Consumed Percentage" は 100% に達します。
- 不十分なディスクの種類: I/O 集中型アプリケーションのパフォーマンスの低いディスクの種類 (Standard HDD など) を選択すると、IOPS の制限が発生する可能性があります。
- 最適化されていないディスク ストライプ サイズ: ストレージ構成がワークロード用に最適化されていない場合、最適でない IOPS パフォーマンスにつながる可能性があります。
データ ディスクの IOPS 制限を超えないようにするには、次の手順を検討してください。
- 不要な I/O 操作を最小限に抑えるために、SQL クエリとデータベース設計を最適化します。
- アプリケーションの IOPS 要件に一致する適切なディスクの種類 (Standard SSD または Premium SSD) を選択します。
- ディスク サイズを大きくして、使用可能な IOPS 容量を増やします。
- RAID 構成を使用して、複数のデータ ディスクに I/O を分散します。
データ ディスク帯域幅の消費率
Data Disk Bandwidth Consumed Percentage Azure メトリックは、ディスク レベルでの帯域幅使用率を測定します。 一般に、高スループットのニーズは、データ ウェアハウス、データ マート、レポート、ETL、およびその他のデータ分析ワークロードに関連しています。
次のシナリオまたは条件は、データ ディスクの帯域幅の制限を超える可能性があります。
- 大きなデータ転送: ディスクと SQL データベース間の大規模なアプリケーション データ転送が頻繁に行われると、使用可能なデータ ディスク帯域幅がすぐに消費される可能性があります。
- 一括データ読み込み: 一括データの挿入、更新、またはインポートに関連付けられているディスク転送アクティビティは、高帯域幅の消費につながる可能性があります。
- データ ウェアハウスまたは分析: 大量のデータ ウェアハウス、分析処理、またはレポートを含むアプリケーションでは、大量のデータ移動が発生し、帯域幅の制限を超える可能性があります。
- 高いデータ冗長性テクノロジ/レプリケーション: 関連するデータ コピーでは、ディスク ベースのレプリケーション、データ ミラーリング、またはその他の冗長性メカニズムが使用され、帯域幅の飽和に寄与する可能性があります。
- データのバックアップと復元: 頻繁なデータ バックアップ、スナップショット、または復元プロセスでは、大量のデータ ディスク帯域幅が消費される可能性があります。
- 並列クエリ実行: 大規模なデータ スキャンまたは結合を伴う並列クエリは、帯域幅の使用率につながる大量のデータ移動につながる可能性があります。
- ネットワークトラフィックの増加:仮想マシンと他のリソース間のデータ転送など、ネットワーク活動が多いと、データディスクの帯域幅の可用性に間接的に影響を及ぼすことがあります。
- 不十分なディスクの種類: データ転送要件が高いアプリケーションでパフォーマンスの低いディスクの種類を選択すると、帯域幅の制限を超える可能性があります。
- 同時データ集中型操作: 複数の同時実行プロセスまたはセッションが同じディスク上のデータにアクセスして転送すると、帯域幅の制限に達する可能性があります。
- 最適化されていないクエリまたは ETL プロセス: 最適化されていない SQL クエリまたは抽出、変換、読み込み (ETL) プロセスは、過剰なデータ移動を引き起こす可能性があります。その結果、帯域幅が過剰に消費される可能性があります。
データ ディスクの帯域幅制限を超えないようにするには、次の手順を検討してください。
- データ転送操作を最適化して、不要なデータ移動を最小限に抑えます。
- Premium SSD や Premium SSD v2 などの帯域幅容量を提供する、パフォーマンスの高いディスクの種類の使用を検討してください。
- パーティション分割やシャーディングなどの手法を使用して、複数のディスクにデータを分散します。
- クエリとデータ処理を最適化して並列化し、データ移動を減らします。
- 圧縮と効率的なデータ ストレージ メカニズムを使用して、転送されるデータの量を減らします。
- パフォーマンス メトリックを監視し、必要に応じてストレージ構成をスケールアップします。 Premium SSD v2 を使用すると、必要に応じて IOPS とスループットを必要に応じてスケーリングできます。
- パフォーマンス メトリックを定期的に監視および分析して、IOPS の制限の原因を特定し、SQL 仮想マシンのストレージ パフォーマンスを最適化するための適切なアクションを実行することが重要です。
ヒント
パフォーマンス メトリックの定期的な監視、データ転送操作のチューニング、ディスク構成の最適化により、SQL 仮想マシンのデータ ディスクのパフォーマンスが制限を超えることなく最適な状態を維持できるようにすることができます。
調整なしの待機時間
調整なしの待機時間とは、ストレージ システムが最大 IOPS またはスループットの制限に達していない場合でも発生するデータ アクセスまたは処理の遅延を指します。 Azure VM の待機時間は、オペレーティング システムの I/O スタック、SQL Server処理、ネットワーク オーバーヘッド、ハイパーバイザー スケジューリングなど、さまざまなソースから発生する可能性があります。 待機時間の原因を特定することは、Azure VM のSQL Serverパフォーマンスを最適化するために重要です。
調整なしで待機時間が検出された場合、[ストレージ] ウィンドウの [I/O 分析] タブに次の警告が表示されます。Warning: High disk latency detected without throttling。
調整なしで待機時間が発生する可能性がある原因を次に示します。
- CPU 使用率が高い: CPU の負荷が高いと、CPU が暗号化、圧縮、クエリ実行などのタスクでビジー状態であるため、I/O 操作が遅くなる可能性があります。 これは、コア数が少ない VM では特に一般的です。 CPU サイクルが使用できない場合、I/O 要求は処理されるまで長く待機でき、ストレージの制限に達しない場合でも待機時間が長くなります。 たとえば、データの暗号化など、CPU を集中的に使用するプロセスを実行している VM では、I/O 操作SQL Server遅延し、クエリの応答時間が遅くなる可能性があります。
- VM 上の十分なメモリ: SQL Serverでは、ディスク I/O の必要性を減らすデータをキャッシュするためにメモリが重要です。 メモリが制約されている場合、SQL Serverはディスクから読み取る頻度が高くなり、待機時間が長くなる可能性があります。 これは、メモリが少ない VM や、メモリ集中型のバックグラウンド プロセスがリソースを競合する場合に特に関連します。 これにより、IOPS の制限に達していない場合でも、ワークロードを処理するために必要なディスク操作の頻度が増えるので、ストレージの待機時間が間接的に長くなる可能性があります。
- バックグラウンド プロセス: VM 上のその他のプロセス (ウイルス対策ソフトウェア、バックアップ、メンテナンス タスク (Windows Update など) など) では、CPU、メモリ、ディスク I/O リソースが消費され、SQL Server操作が遅れる可能性があります。 非効率的なフィルター ドライバーは、この効果を悪化させる可能性があります。 これらのプロセスは、システム リソースのSQL Serverと競合するため、ストレージ待機時間として表示される I/O 遅延が発生します。 たとえば、多数のファイルを同時に読み取るウイルス対策スキャンでは、SQL Serverで使用できるディスク帯域幅を減らすことができます。これにより、データベース トランザクションの待機時間が長くなります。 さらに、適切なウイルス対策の除外がない場合、主にディスク I/O の増加、フィルター ドライバーの干渉、リソースの競合によって、Azure VM のSQL Serverを調整することなく待機時間の問題が発生する可能性があります。
- 低階層ストレージの使用量: Premium SSD や Ultra Disks ではなく Standard HDD などの下位レベルのストレージ オプションを選択すると、IOPS 制限に達しなくても、これらのディスク固有の設計によりベースライン待機時間が長くなります。 コスト効率の高い低層ストレージは、パフォーマンス重視のSQL Serverワークロードには最適化されていないため、データ アクセスが遅くなります。 たとえば、Standard HDD を使用してコストを節約しているお客様は、ディスクの待機時間が自然に長いため、クエリのパフォーマンスが低下する可能性があります。
- 不十分なストレージ構成: SQL Serverのワークロードに最適化するようにストレージを構成しないと、調整できない待機時間が発生する可能性があります。 たとえば、ディスク キャッシュの設定が正しくないと、パフォーマンスが低下する可能性があります。 Azure VM で Premium SSD v1 とSQL Serverを使用する場合は、データ ディスクの読み取り専用キャッシュを有効にし、ログ ディスクのキャッシュを無効にすることをお勧めします。 キャッシュが正しく構成されていないと、読み取り操作または書き込み操作が遅くなる可能性があります。 たとえば、SQL Serverデータ ファイルをホストするデータ ディスクで読み取りキャッシュを無効にすると、読み取り負荷の高いワークロードの効率が低下し、待機時間が長くなります。
- SQL Server データベースの競合: 非効率的なクエリ (インデックス付き参照ではなく完全なテーブル スキャンなど) や、SQL Server内のロック競合により、I/O 要求が増加したり、データ アクセスが遅延したりする可能性があり、これはストレージ待機時間として現れます。 アプリケーション レベルの問題では、特にトランザクション ワークロードで一般的な小規模でランダムな I/O パターンを使用して、制限を超えることなくストレージ サブシステムを負担する可能性があります。 たとえば、大きなデータセットに対して完全なテーブル スキャンを実行する最適化が不十分なクエリでは、ディスクから過剰なデータが読み取られ、インデックス付きクエリと比較して I/O の読み込みと待機時間が増加します。
調整なしで待機時間が発生する場合は、待機時間に対処するために次の手順を検討してください。
- CPU 使用率の監視と管理: Azure Monitorやリソース モニターなどのツールを使用して CPU 使用率を追跡します。 CPU 負荷が高い場合は、SQL クエリを最適化するか、仮想コアが多い VM にアップグレードします。
- メモリ使用量を監視: メモリ対仮想コアの比率が高い E シリーズや M シリーズなどの VM サイズを使用して、SQL Server のワークロードに対して十分なメモリを VM サイズが備えていることを確認してください。 パフォーマンス モニターまたはAzure Monitorを使用してメモリ使用量を監視し、圧力ポイントを識別します。 必要に応じて、メモリのスケールアップを検討してください。
- バックグラウンド タスクを慎重にスケジュールする: リソースのSQL Serverとの競合を回避するために、ピーク外の時間帯にリソース負荷の高いタスク (バックアップやウイルス対策スキャンなど) を実行します。
- 適切なストレージ層を選択する: 下位層のストレージ (Standard HDD など) がパフォーマンスニーズを満たしているかどうかを評価します。 重要なSQL Serverワークロードの場合は、Premium SSD または Ultra Disks を選択して待機時間を最小限に抑えます。
- キャッシュを正しく構成する: Premium SSD (v1) の場合は、データ ディスクの読み取り専用キャッシュを設定し、ログ ディスクのキャッシュは設定しません。 Premium SSD v2 と Ultra Disks ではキャッシュがサポートされていないため、VM またはストレージの変更後の設定を確認します。
- SQL Serverのパフォーマンスを最適化する: I/O の需要を減らすためにクエリを見直して調整します。 インデックスを実装し、テーブル全体のスキャンを回避し、ロックの競合を解決して効率を向上させます。 ベスト プラクティス分析 機能を使用して、パフォーマンスを向上できる構成オプションを特定します。
- ウイルス対策の除外が正しいことを確認する: 適切な除外を実装し、負荷の下でテストし、スキャンを適切にスケジュールすることで、待機時間の問題を軽減し、セキュリティ バランスで最適なパフォーマンスを確保できます。
I/O関連のベストプラクティス
構成が不十分なストレージ システムはパフォーマンスの問題につながる可能性があるため、Azure ポータルの Storage ウィンドウを使用して、SQL のベスト プラクティス評価 ルールのディスク固有のサブセットを実行し、Azure VM のSQL Serverに関するストレージ構成の問題を特定できます。 SQL のベスト プラクティス機能は、SQL Assessment API に基づいています。
GitHubに関する推奨事項の完全な一覧を表示できます。 GitHubのルールの
- AzSqlVmSize
- AzDataDiskCache
- AzDataDiskStriping
- AzDataOnDataDisks
- AzDbDefaultLocation
- AzDiskColumnCount
- AzErrorLogLocation
- AzPremSSDデータファイル
- AzTempDbFileLocation (一時的なデータベースファイルの場所)
- AzTranLogDiskCache
- NtfsBlockSizeNotFormatted
- メモリ内のロックされたページ
[I/O 関連のベスト プラクティス] タブで、評価を実行 して構成の評価を開始します。完了するまでに数分かかります (データベースとオブジェクトが多数ある場合を除く)。 または、利用可能な最新の結果のタイムスタンプが表示された場合は、最新の結果を取得を使用して、以前の評価の結果を確認できます。
PowerShell を使用して I/O を分析する
I/O 分析 PowerShell スクリプトを使用して、SQL Server VM の I/O パフォーマンスを分析することもできます。
# Enter parameters
$subscriptionId = Read-Host "<Subscription ID>"
$resourceGroup = Read-Host "<Resource Group>"
$vmName = Read-Host "<Virtual machine name>"
# Set resource details
$resourceType = "Microsoft.Compute/virtualMachines"
$resourceId = "/subscriptions/$subscriptionId/resourceGroups/$resourceGroup/providers/$resourceType/$vmName"
# Get Azure access token
$accessToken = az account get-access-token --query accessToken -o tsv
# Invoke Azure Monitor Metrics API
function Get-Metrics {
[CmdletBinding()]
param (
[string]$accessToken,
[string]$resourceId,
[string]$metricNames,
[string]$apiVersion = "2023-10-01"
)
try {
$startTime = (Get-Date).AddHours(-24).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')
$endTime = (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')
$timespan = "$startTime/$endTime"
Write-Verbose "Evaluating timespan: $timespan"
$uri = "https://management.azure.com$resourceId/providers/Microsoft.Insights/metrics?api-version=$apiVersion&metricnames=$metricNames&aggregation=maximum&interval=PT1M×pan=$timespan"
$headers = @{ "Authorization" = "Bearer $accessToken"; "Content-Type" = "application/json" }
$response = Invoke-RestMethod -Uri $uri -Headers $headers -Method Get
if ($response) {
Write-Verbose "API response successfully retrieved."
return $response
} else {
Write-Error "No response from API."
}
} catch {
Write-Error "Error retrieving metrics: $_"
}
}
# Check if data disk latency violates thresholds
function Check-Latency {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[Object]$metrics,
[Parameter()]
[int]$latencyThreshold = 500,
[Parameter()]
[int]$consecutiveCount = 5
)
$violationTimes = @()
foreach ($metric in $metrics.value) {
if ($metric.name.value -eq "Data Disk Latency") {
$count = 0
foreach ($dataPoint in $metric.timeseries[0].data) {
if ($dataPoint.maximum -gt $latencyThreshold) {
$count++
if ($count -ge $consecutiveCount) {
$violationTimes += $dataPoint.timeStamp
$count = 0 # Reset count after recording a violation
}
} else {
$count = 0 # Reset count if the sequence is broken
}
}
}
}
if ($violationTimes.Count -gt 0) {
Write-Verbose "Latency violations detected."
return @{ "Flag" = $true; "Times" = $violationTimes }
} else {
Write-Verbose "No latency violations detected."
return @{ "Flag" = $false }
}
}
# Check metrics other than latency to evaluate for throttling
function Check-OtherMetricsThrottled {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[Object]$metrics,
[Parameter()]
[int]$PercentageThreshold = 90,
[Parameter()]
[int]$consecutiveCount = 5
)
$violatedMetrics = @()
foreach ($metric in $metrics.value) {
$count = 0
foreach ($dataPoint in $metric.timeseries[0].data) {
if ($dataPoint.maximum -gt $PercentageThreshold) {
$count++
if ($count -ge $consecutiveCount) {
$violatedMetrics += @{ "Metric" = $metric.name.localizedValue; "Time" = $dataPoint.timeStamp; "Value" = $dataPoint.maximum }
break
}
} else {
$count = 0
}
}
}
if ($violatedMetrics.Count -gt 0) {
Write-Verbose "Other metrics violations detected."
} else {
Write-Verbose "No other metrics violations detected."
}
return $violatedMetrics
}
# Compare times for latency & other throttled metrics. Logs the volations with values & timestamps
function CompareTimes {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[Hashtable]$latencyResult,
[Parameter(Mandatory = $true)]
[Array]$otherMetrics
)
foreach ($metric in $otherMetrics) {
$otherDateTime = [DateTime]$metric["Time"]
$isWithinFiveMinutes = $false
$closestLatencyTime = $null
$closestTimeDifference = [int]::MaxValue
foreach ($latencyTime in $latencyResult.Times) {
$latencyDateTime = [DateTime]$latencyTime
$timeDifference = [Math]::Abs(($otherDateTime - $latencyDateTime).TotalMinutes)
if ($timeDifference -le 5) {
$isWithinFiveMinutes = $true
if ($timeDifference -lt $closestTimeDifference) {
$closestTimeDifference = $timeDifference
$closestLatencyTime = $latencyTime
}
}
}
if ($isWithinFiveMinutes) {
if ($otherDateTime -lt $closestLatencyTime) {
Write-Host "`n $($metric["Metric"]) limit was hit before latency spiked at $closestLatencyTime with value $($metric["Value"]). `n"
} else {
Write-Host "`n $($metric["Metric"]) hit its limit with value $($metric["Value"]) at $($metric["Time"])."
Write-Host "Latency spiked at $closestLatencyTime before $($metric["Metric"]) hit its limit `n"
}
} else {
Write-Host "`n Metric: $($metric["Metric"]) exceeded its threshold with a value of $($metric["Value"]) at $($metric["Time"]), but this was not within 5 minutes of any latency spikes."
}
}
}
# Prompt user for latency threshold
$latencyThreshold = Read-Host "Enter Latency Threshold (default is 500)"
if (-not [int]::TryParse($latencyThreshold, [ref]0)) {
$latencyThreshold = 500 # Use default if invalid input
Write-Host "No valid input provided. Using Default 500ms for disk latency threshold"
}
# Execute main logic
$latencyMetrics = Get-Metrics -accessToken $accessToken -resourceId $resourceId -metricNames "Data Disk Latency"
$latencyResult = Check-Latency -metrics $latencyMetrics -latencyThreshold $latencyThreshold
if ($latencyResult.Flag) {
# If latency is flagged, check for other metrics. If there is no disk latency, machine is likely not throttled but only at high consumption
Write-Verbose "Checking the following metrics: Data Disk Bandwidth Consumed Percentage,Data Disk IOPS Consumed Percentage,VM Cached Bandwidth Consumed Percentage,VM Cached IOPS Consumed Percentage,VM Uncached Bandwidth Consumed Percentage,VM Uncached IOPS Consumed Percentage"
$DiskVMMetrics = Get-Metrics -accessToken $accessToken -resourceId $resourceId -metricNames "Data Disk Bandwidth Consumed Percentage,Data Disk IOPS Consumed Percentage,VM Cached Bandwidth Consumed Percentage,VM Cached IOPS Consumed Percentage,VM Uncached Bandwidth Consumed Percentage,VM Uncached IOPS Consumed Percentage"
$additionalMetrics = Check-OtherMetricsThrottled -metrics $DiskVMMetrics
if ($additionalMetrics.Count -gt 0) {
CompareTimes $latencyResult $additionalMetrics
} else {
Write-Host "No metrics violations detected besides latency."
}
} else {
Write-Host "No latency issues detected."
}
次のステップ
- SQL のベスト プラクティス評価を実行して、パフォーマンスの問題につながる可能性のある構成の誤りを特定します。