このサイトには、待機統計に関連する多数のブログ投稿があります。これらは、SQLServerのパフォーマンスの問題をトラブルシューティングするときに使用できる最も重要なメトリックの1つです。待機統計はSQLServer2005で利用可能になり、従来はsys.dm_os_wait_statisticsを介してインスタンスレベルで待機を表してきました。この情報は、システムパフォーマンス全般のトラブルシューティングに役立ちますが、クエリパフォーマンスを見ると、待機情報は、クエリが実行されているとき、およびsys.dm_os_waiting_tasksを介してリソースを待機している場合にのみ表示されます。 sys.dm_os_waiting_tasksのデータは一時的なものであり(現在待機しているものです)、後でパフォーマンスを調整するためのクエリの存続期間中、キャプチャして保持するのは簡単ではありません。
SQL Server 2016では、新しいDMV sys.dm_exec_session_wait_statsが公開されています。これは、既存のアクティブなセッションの待機に関する情報を提供します。 session_idがわかっている場合は、クエリの開始時と完了時の待機を追跡できます(クエリの最初と最後で情報をスナップショットしてから、情報を比較します)。課題は、クエリのsession_idを知っている必要があり、事前にデータキャプチャを設定する必要があることです。これは、優先度の高い問題の真っ只中にある場合は簡単ではありません。
待機統計情報は、SQL Server2016SP1以降の実際の実行プランに存在します。上位10の待機のみがキャプチャされ、このデータが表す内容に関して制限があります。たとえば、CXPACKETは無視され、出力には含まれませんが、2016SP2および2017CU3以降に含まれます。代わりに、無関係な並列処理待機がCXCONSUMERによってキャプチャされます(実際の計画待機には含まれません)。
では、特定のクエリが本当に待機しているものをどのように確認できますか?クエリストアを使用できます! SQL Server 2017には、クエリストアでの待機統計情報のキャプチャが含まれており、この機能はAzureSQLデータベースでも使用できます。待機統計はクエリプランに関連付けられており、実行時の統計と同様に、時間の経過とともに取得されます。クエリストアに待機統計情報を追加することは、最初のリリース後の最大の機能リクエストであり、そのすべての情報が一緒になって強力なトラブルシューティング機能を作成します。
はじめに
クエリストアでの待機統計キャプチャは、AzureSQLDatabaseではデフォルトで有効になっています。 SQL Server 2017で新しいデータベースが作成されるか、データベースがSQL Server 2014以前からアップグレードされると、クエリストアはデフォルトで無効になります…したがって、待機統計のキャプチャは無効になります。データベースをSQLServer2016からアップグレードするときに、クエリストアが有効になっている場合は、アップグレード時にクエリストアの待機統計収集が有効になります。
デモンストレーションの目的で、WideWorldImportersデータベースを復元してから、以下のクエリを実行してクエリストアを有効にし、以前に存在していた可能性のあるデータをすべて消去しました(これはサンプルデータベースであるため、必要な場合のみ):
ALTER DATABASE [WideWorldImporters] SET QUERY_STORE = ON; GO ALTER DATABASE [WideWorldImporters] SET QUERY_STORE ( OPERATION_MODE = READ_WRITE ); GO ALTER DATABASE [WideWorldImporters] SET QUERY_STORE CLEAR; GO
上記のステートメントではデフォルト設定が使用されます。オプションのいずれかを変更する場合は、UIまたはALTERDATABASEステートメントを使用して変更できます。クエリストアが有効になると、クエリテキスト、プラン、実行時統計、待機統計などのクエリデータのキャプチャが開始されます。
待機統計を見る
一部のデータを生成するために、並列クエリを繰り返し実行するストアドプロシージャを作成します。
DROP PROCEDURE IF EXISTS [Sales].[OrderInfo]; GO CREATE PROCEDURE [Sales].[OrderInfo] AS BEGIN WHILE 1=1 BEGIN SELECT * FROM Sales.OrderLines ol INNER JOIN Warehouse.StockItems s ON ol.StockItemID = s.StockItemID OPTION (QUERYTRACEON 8649); END END
次に、次のコードを使用して.cmdファイルを作成します。
start sqlcmd -S WIN2016 \ SQL2017 -d WideWorldImporters -q"EXECUTE[Sales]。[OrderInfo];"exit
これにより、 Management Studio内でSPを実行すると、ASYNC_NETWORK_IOの大幅な待機が発生します。並列処理に関連する待機を確認したいと思います。 .cmdファイルを保存し、ダブルクリックして実行します。複数のファイルを実行することにより、追加の負荷を生成できます。このシナリオでは、他のワークロードがないため、主にこのクエリに関連する待機が表示されます。さらに多くの待機データを生成したい場合は、WideWorldImportersデータベースに対して他のクエリを同時に実行してください。
数分後、コマンドファイルを停止し、Management Studio内のWideWorldImportersデータベースを展開して、クエリストアフォルダーとその下のレポートを表示します。 Top Resource Consuming Queriesレポートを開くと、ストアドプロシージャクエリがトップクエリとして表示されます。
このレポートのデフォルトのビューには、合計期間が最も長いクエリが表示されます。待機統計に基づいてクエリを表示するには、[構成]ボタンを選択し、[待機時間(ms)]に変更します。
レポートビューの[構成]ボタン(右上)最初のクエリのバーにカーソルを合わせると、クエリの待機時間が表示されます。このビューは現在、UIで待機情報を表示する唯一の方法ですが、待機統計に固有の追加のレポートがManagementStudioの将来のリリースで提供されることを期待しています。
UIで情報を待つ
しばらく待機統計を使用したことがある方は、待機タイプの説明が異なることに気付くでしょう。つまり、並列処理を示すCXPACKET待機タイプの代わりに、「並列処理待機タイプ」と表示されます。これは、クエリストアの基本的な違いです。待機タイプはカテゴリにグループ化されています。この時点でSQLServerには900を超えるさまざまな待機タイプがあり、それぞれを個別に追跡しようとすると非常にコストがかかります。さらに、Query Storeは、すべてのデータプロフェッショナルを念頭に置いて設計されています。パフォーマンス調整の専門家でも、SQL Serverの動作を理解し始めたばかりでも、QueryStoreを使用してパフォーマンスの低いクエリを簡単に見つけることができます。これは、待機情報を理解しやすくすることも意味します。待機カテゴリとその中の待機タイプの完全なリストについては、sys.query_store_wait_statsのドキュメントにアクセスしてください。
T-SQLを使用して待機情報を表示することもできます。クエリの例は次のとおりです。これには、クエリ、そのクエリのplan_id(s)、および指定された時間間隔の統計の待機が含まれます。
SELECT TOP (10) [ws].[wait_category_desc], [ws].[avg_query_wait_time_ms], [ws].[total_query_wait_time_ms], [ws].[plan_id], [qt].[query_sql_text], [rsi].[start_time], [rsi].[end_time] FROM [sys].[query_store_query_text] [qt] JOIN [sys].[query_store_query] [q] ON [qt].[query_text_id] = [q].[query_text_id] JOIN [sys].[query_store_plan] [qp] ON [q].[query_id] = [qp].[query_id] JOIN [sys].[query_store_runtime_stats] [rs] ON [qp].[plan_id] = [rs].[plan_id] JOIN [sys].[query_store_runtime_stats_interval] [rsi] ON [rs].[runtime_stats_interval_id] = [rsi].[runtime_stats_interval_id] JOIN [sys].[query_store_wait_stats] [ws] ON [ws].[runtime_stats_interval_id] = [rs].[runtime_stats_interval_id] AND [ws].[plan_id] = [qp].[plan_id] WHERE [rsi].[end_time] > DATEADD(MINUTE, -5, GETUTCDATE()) AND [ws].[execution_type] = 0 ORDER BY [ws].[avg_query_wait_time_ms] DESC;
これで、特定のクエリとその計画のすべての待機を確認できますが、パフォーマンスをさらに掘り下げて、たとえば、クエリが並行して実行されている理由(おそらく必要ない場合)やクエリをブロックしている可能性があるもの。待機統計は、実行時統計と同様に、時間の経過とともにクエリプランに関連付けられることに注意してください。この出力では、クエリストアの間隔の長さが10分に設定されているため、待機統計はその10分間隔(2017年11月21日の午後11時50分から2017年11月22日の深夜0時まで)の各プランの待機統計になります。デフォルトでは、クエリストアを有効にしたときの間隔の長さは60分です。
概要
待機統計と個々のクエリプランを組み合わせることで、システムとクエリのパフォーマンスのトラブルシューティングを行う際に、クエリストアがさらに手ごわいツールになります。クエリストアは、クエリ、プラン、パフォーマンスメトリック、および待機統計をすべて1つの場所でネイティブにキャプチャできる唯一の機能です。無数の待機タイプに慣れている方は、クエリストアで使用されるカテゴリへの調整がシームレスに行われる必要があります。統計を待つのが初めての人にとって、カテゴリはクエリが待っているリソースを理解し始めるのに最適な場所です。