sql >> データベース >  >> RDS >> Database

AzureSQLデータベースの帯域幅に適したクエリプロファイリング

    SQL Serverは常に、簡単に使用できる行セット形式でアドホックベースでライブクエリをキャプチャする機能を提供してきました。最初はレガシーSQL Server Profilerを使用し、後でSSMSの拡張イベントを使用します。クエリイベントには、個別のCPUおよびIOメトリックと、パラメータスニッフィングなどのクエリパフォーマンスの問題をトラブルシューティングするためのキーとなるランタイムパラメータが含まれるため、この機能はパフォーマンスチューニング時に役立ちます。さらに、クエリイベントには、クライアントのホスト名、アプリケーション名、ログイン、WindowsプロセスIDなどの他の重要な要素が含まれています。

    集計はいつでも取得できます 正規化のパフォーマンスメトリック DMVまたはクエリストアからのクエリですが、コンパイル済みのみが含まれています パラメータであり、前述の要素はありません。これは役に立ちますが、同じではありません。たとえば、過去24時間に20億回の読み取りを行ったクエリで使用された特定のパラメータの組み合わせを確認したり、CPUを最も消費しているアプリケーションを見つけたりする必要がある場合は、運が悪いです。

    Azure SQL Databaseはレガシープロファイラーではサポートされていません。Microsoftは信頼性の理由からXEventsストリーミングプロバイダー(sys.fn_MSxe_read_event_stream TVF)を無効にしているため、XEセッションを起動してSSMSで「ライブデータを監視」することはできません。 AzurePortalのQueryPerformanceInsightsはQueryStoreによってサポートされているため、実際のクエリイベントではなく、正規化されたクエリと集計されたパフォーマンスデータのみがあります。

    そのため、数年間、行き詰まりました。AzureSQLデータベースをプロファイリングするための唯一のオプションは、AzureStorageを使用してリングバッファーまたはファイルターゲットに書き込むXEventsトレースを手動で作成することでした。どちらも最適ではありません。ここでJonathanKehayiasがカバーしている4MB形式のXML制限のため、T-SQLクエリでリングバッファを使用すると問題が発生する可能性があり、ファイルターゲットにはかなりのフープジャンプと追加費用が必要です。どちらもXEデータを手動でクエリする必要があるため、従来の意味で正確に「ライブ」ではありません。

    新規を入力します SQLServerプロファイラー

    AzureDataStudio用のSQLServerProfiler拡張機能について知ったとき、MicrosoftがAzureSQLDatabaseでのライブクエリキャプチャ用のグラフィカルソリューションを最終的に提供するのを見てうれしく思いました。残念ながら、私の興奮はいくつかの理由で短命でした。

    まず、レガシープロファイラーからの恐ろしい「標準」トレースが、AzureSQLデータベースのADSプロファイラーXEセッションのモデルとして使用されているようです ADS_Standard_Azureという名前 デフォルトでは。 (完全なSQL Serverに使用されるXEセッションは似ています。)数年前にブログを書きましたが、今でも信じているように、標準トレースは、レガシープロファイラーがあまり評価されていない主な理由です。これには、SQLバッチ開始などの役に立たないフィルタリングできないイベントが複数含まれています。 、ログイン およびログアウト 、その結果、パフォーマンスチューニングに実際の価値はありません。さらに、レガシーProfilerで使用される同期行セットトレースアーキテクチャでは、イベント量が多いと、ビジー状態のシステムのパフォーマンスに影響を与える可能性があります。どういうわけか、これは消えません!

    レガシープロファイラーの「標準」トレースイベント

    ADSプロファイラー「ADS_Standard_Azure」XEイベント
    –見覚えがありますか?

    次に、最大サイズが8MBまたは1000イベントのいずれか早い方のリングバッファを使用します。ログイン/ログアウトイベントは小さいため、8MBの制限、または4MB形式のXMLの制限に達するずっと前に1000イベントに達することがよくあります。ただし、SQLイベントが適度に混在している場合、テストではリングバッファXMLは1000イベントで2〜3 MBのままになります。問題は、プロファイラ拡張機能がポーリングして更新するたびに、このバッファ全体がネットワーク全体にプルされることです。そのグリッド 、これは1秒ごとまたは前回のポーリングの期間のいずれか長い方です。次に、XMLはADS Profiler拡張機能によってクライアント側で解析され、前回のポーリング以降に新しいイベントが特定され、新しいイベントがグリッドに追加されます。

    リングバッファは、適度にビジーなサーバーでもほぼ瞬時にいっぱいになります。正味の効果は、AzureSQLデータベースからネットワーク全体で毎秒40メガビット以上をすばやくプルすることです。 。これは、1分あたり300メガバイト、つまり1時間あたり18ギガバイトに相当します!

    ADSプロファイラー拡張機能からのネットワークヒット(4分範囲)

    私の最初の恐怖は、これが次のAzure請求書で巨額の出口料金につながる可能性があることでしたが、私たち自身のAzureサブスクリプションを見ると、AzureSQLDBのネットワークトラフィックが課金されていることを確認できませんでした。 AzureMVPであるSentryOneのMikeWood(b | t)は、答えを見つけるために数週間を費やし、最終的にMicrosoftから、ネットワーク出力は現在Azure SQL DBに対して課金されていないという連絡を受けましたが、これはいつでも変更される可能性があります。それでも、1時間あたり18 GBのクエリデータを取得することは責任を負わないようであり、次のNetflixの一気見セッションに確実にダンパーをかける可能性があります。

    プロファイラーUIを使用してフィルターを設定すると、データの確認が容易になりますが、クライアント側で動作するため、ネットワークヒットを減らすことはできません。

    更新されたXEセッション

    ADSプロファイラーのネットワーク負荷を軽減し、クエリパフォーマンスの調整のためにデータをより消費しやすくするための迅速な解決策は、 ADS_Standard_Azureを更新することです。 XEセッション。以下は、次のようなスクリプトです。

    • 不要なイベントを削除します:

      • sqlserver.attention
      • sqlserver.existing_connection
      • sqlserver.login
      • sqlserver.logout
      • sqlserver.sql_batch_starting
    • 残りのイベントに1秒(1000000マイクロ秒)を超える期間のしきい値を設定します:

      • sqlserver.rpc_completed
      • sqlserver.sql_batch_completed
    • リングバッファの最大サイズを1000から10イベントに減らします

      • ミリ秒単位で10個のイベントが生成され、リングバッファの再循環が速すぎてほとんどのイベントが失われるため、これは元のトレースでは機能しません。ただし、1秒の継続時間フィルターを使用すると、イベントフローははるかに少なくなり、ADSプロファイラーで使用される1秒のポーリング間隔で10個のイベントが適切に機能するはずです。
    ALTER EVENT SESSION [ADS_Standard_Azure] ON DATABASE 
    DROP EVENT sqlserver.attention,
    DROP EVENT sqlserver.existing_connection,
    DROP EVENT sqlserver.login,
    DROP EVENT sqlserver.logout,
    DROP EVENT sqlserver.rpc_completed,
    DROP EVENT sqlserver.sql_batch_completed,
    DROP EVENT sqlserver.sql_batch_starting
    GO
     
    ALTER EVENT SESSION [ADS_Standard_Azure] ON DATABASE 
    ADD EVENT sqlserver.rpc_completed(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.query_hash,sqlserver.session_id,sqlserver.username)
          WHERE (([package0].[equal_boolean]([sqlserver].[is_system],(0))) AND ([duration] >= (1000000)))),
    ADD EVENT sqlserver.sql_batch_completed(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.query_hash,sqlserver.session_id,sqlserver.username)
          WHERE (([package0].[equal_boolean]([sqlserver].[is_system],(0))) AND ([duration] >= (1000000))))
    GO
     
    ALTER EVENT SESSION [ADS_Standard_Azure] ON DATABASE 
    DROP TARGET package0.ring_buffer
    GO
     
    ALTER EVENT SESSION [ADS_Standard_Azure] ON DATABASE 
    ADD TARGET package0.ring_buffer(SET max_events_limit=(10),max_memory=(51200))
    GO

    XEセッションを更新するスクリプトを適用した後、消防ホースはすぐに細流になります:

    ADSProfilerXEセッションの更新後のネットワークヒットの削減

    さらに軽量の代替品

    SQLSentryとそれに対応するSaaSのSentryOneMonitorは、Azure SQL Databaseからクエリをキャプチャするために私が知っている他の唯一のソリューションであり、上記のADSProfiler用に最適化されたXEセッションよりもかなり軽量な革新的なアプローチを使用しています。他の高度な機能の中でも、クライアントのホスト名、アプリケーション、ログインごとに簡単に集計し、統合されたプランエクスプローラーを使用して分析用のクエリプランを自動的にキャプチャできます。

    AzureSQLデータベースからキャプチャされたクエリとプランを表示するSentryOneモニター

    締めくくり

    Microsoftは、ADS Profiler拡張機能を引き続き拡張すると述べており、拡張する場合は、上記の問題に対処することを期待しています。ここに問題を記録しました。それまでの間、更新されたスクリプトにより、AzureSQLデータベースのより安全で帯域幅に優しいクエリプロファイリングエクスペリエンスが実現します。


    1. 割り当て順序スキャン

    2. UnixタイムスタンプをPostgreSQLで日付/時刻値に変換する方法

    3. オフライン再編成ウィザードの使用

    4. SecurityAdvisorMySQLアラートを修正する方法