Benjamin Nevarezは、カリフォルニア州ロサンゼルスを拠点とする独立コンサルタントであり、SQLServerクエリのチューニングと最適化を専門としています。彼は「SQLServer2014クエリの調整と最適化」および「SQLServerクエリオプティマイザーの内部」の著者であり、「SQLServer2012の内部」の共著者です。リレーショナルデータベースで20年以上の経験を持つベンジャミンは、PASSサミット、SQL Server接続、SQLBitsなどの多くのSQLServer会議でも講演を行ってきました。ベンジャミンのブログはhttp://www.benjaminnevarez.comにあります。また、メールでbenjaminnevarez dot comに、ツイッターで@BenjaminNevarezにアクセスすることもできます。
SQL Serverのアップグレード後にプランのリグレッションを見つけ、以前の実行プランが何であったかを知りたいと思ったことはありませんか?クエリが予期せずに新しい実行プランを取得したために、クエリのパフォーマンスの問題が発生したことがありますか?前回のPASSサミットで、ConorCunninghamは新しいSQLServer機能を発見しました。これは、実行プランのこれらの変更やその他の変更に関連するパフォーマンスの問題を解決するのに役立ちます。
クエリストアと呼ばれるこの機能は、計画の変更に関連するパフォーマンスの問題を解決するのに役立ち、SQL Azureで間もなく利用可能になり、SQLServerの次のバージョンで利用できるようになります。 SQLServerのEnterpriseEditionで利用できるようになる予定ですが、Standardまたはその他のエディションで利用できるかどうかはまだわかりません。クエリストアの利点を理解するために、クエリのトラブルシューティングプロセスについて簡単に説明します。
クエリが遅いのはなぜですか?
クエリが遅いことがパフォーマンスの問題であることがわかったら、次のステップはその理由を見つけることです。明らかに、すべての問題が計画の変更に関連しているわけではありません。正常に実行されているクエリが突然遅くなる理由は複数考えられます。これは、ブロッキングまたは他のシステムリソースの問題に関連している場合があります。他の何かが変わったかもしれませんが、課題は何を見つけることかもしれません。多くの場合、システムリソースの使用状況、クエリの実行統計、パフォーマンス履歴に関するベースラインがありません。そして通常、私たちは古い計画が何であったかわかりません。データ、スキーマ、クエリパラメータなどの変更により、クエリプロセッサが新しいプランを作成した場合があります。
計画の変更
セッションでは、ConorはPicasso Database Query Optimizer Visualizerツールを使用しましたが、名前では言及していませんでしたが、同じクエリのプランが変更された理由を示し、同じクエリに対して異なるプランを選択できるという事実を説明しました。それらの述語の選択性。彼は、クエリオプティマイザチームがインド科学研究所によって開発されたこのツールを使用しているとさえ述べました。視覚化の例(クリックして拡大):
図の各色は異なる計画であり、各計画は述語の選択性に基づいて選択されます。重要な事実は、グラフで境界を越えて別のプランを選択した場合、選択性または推定行数がわずかに変化するだけなので、ほとんどの場合、両方のプランのコストとパフォーマンスは同じである必要があります。これは、たとえば、使用されている述語の対象となる新しい行がテーブルに追加された場合に発生する可能性があります。ただし、場合によっては、主にクエリオプティマイザのコストモデルの制限により、何かを正しくモデル化できないため、新しいプランでは前のプランと比較してパフォーマンスが大きく異なり、アプリケーションに問題が発生する可能性があります。ちなみに、図に示されているプランは、クエリオプティマイザによって選択された最終的なプランです。これを、オプティマイザが1つだけを選択するために検討する必要のある多くの選択肢と混同しないでください。
私の意見では、Conorが直接取り上げなかった重要な事実は、累積的な更新(CU)、サービスパック、またはバージョンのアップグレードの変更後のリグレッションによる計画の変更でした。クエリオプティマイザ内の変更で頭に浮かぶ主な懸念事項は、プランのリグレッションです。プランのリグレッションの恐れは、クエリオプティマイザの改善に対する最大の障害と見なされてきました。リグレッションは、クエリオプティマイザーに修正が適用された後に発生する問題であり、従来の「2つ以上の間違いが正しい」と呼ばれることもあります。これは、たとえば、1つは値を過大評価し、もう1つは値を過小評価する、2つの悪い見積もりが互いに打ち消し合い、幸運にも良い見積もりが得られた場合に発生する可能性があります。これらの値の1つだけを修正すると、誤った見積もりにつながる可能性があり、プラン選択の選択に悪影響を及ぼし、回帰を引き起こす可能性があります。
クエリストアは何をしますか?
Conorは、Query Storeが実行し、次のことを支援できると述べました。
- クエリプランの履歴をシステムに保存します。
- 各クエリプランのパフォーマンスを経時的にキャプチャします。
- 「最近遅くなった」クエリを特定します;
- 計画を迅速に実施できるようにします。そして、
- これがサーバーの再起動、アップグレード、クエリの再コンパイルで機能することを確認してください。
したがって、この機能は、プランと関連するクエリパフォーマンス情報を格納するだけでなく、古いクエリプランを簡単に強制するのにも役立ちます。これにより、多くの場合、パフォーマンスの問題を解決できます。
クエリストアの使用方法
ALTER DATABASE CURRENT SET QUERY_STORE = ON;
を使用して、クエリストアを有効にする必要があります。 声明。現在のSQLAzureサブスクリプションで試しましたが、機能がまだ利用できないようであるため、ステートメントはエラーを返しました。 Conorに連絡したところ、この機能はまもなく利用可能になるとのことでした。
クエリストアを有効にすると、プランとクエリパフォーマンスデータの収集が開始され、クエリストアのテーブルを確認してそのデータを分析できます。現在、SQL Azureでこれらのテーブルを表示できますが、クエリストアを有効にできなかったため、カタログからデータが返されませんでした。
収集された情報を事前に分析してアプリケーションのクエリパフォーマンスの変化を理解するか、パフォーマンスに問題がある場合は遡及的に分析できます。問題を特定したら、従来のクエリ調整手法を使用して問題の修正を試みるか、sp_query_store_force_plan
を使用できます。 以前の計画を強制するためのストアドプロシージャ。プランを強制するには、クエリストアにキャプチャする必要があります。これは、明らかに有効なプランであり(少なくとも収集されたとき、後で詳しく説明します)、以前にクエリオプティマイザによって生成されたことを意味します。プランを強制するには、plan_id
が必要です 、sys.query_store_plan
で利用可能 カタログ。保存されているさまざまなメトリックを確認すると、たとえばsys.dm_exec_query_stats
に保存されているものと非常によく似ています。 、CPU、I / Oなどの特定のメトリックに最適化するかどうかを決定できます。次に、次のようなステートメントを使用できます。
EXEC sys.sp_query_store_force_plan @query_id = 1, @plan_id = 1;
これは、SQL Serverにクエリ1でプラン1を強制するように指示しています。技術的には、プランガイドを使用して同じことを行うことができますが、より複雑になり、最初に必要なプランを手動で収集して見つける必要があります。
クエリストアはどのように機能しますか?
実際に計画を強制するには、バックグラウンドで計画ガイドを使用します。 Conorは、「クエリをコンパイルするときに、そのステートメントに関連付けられたXMLプランのフラグメントを使用してUSEPLANヒントを暗黙的に追加します」と述べています。したがって、プランガイドを使用する必要はもうありません。また、プランガイドを使用する場合と同様に、強制されたプランが正確にあるとは限りませんが、少なくともそれに類似したものであることが保証されていることにも注意してください。プランガイドがどのように機能するかを思い出させるために、この記事を見てください。さらに、プランの強制が機能しない場合があることに注意する必要があります。典型的な例は、スキーマが変更された場合です。つまり、保存されたプランがインデックスを使用しているが、インデックスが存在しなくなった場合です。この場合、SQL Serverはプランを強制できず、通常の最適化を実行し、プラン操作の強制が失敗したという事実をsys.query_store_plan
に記録します。 カタログ。
アーキテクチャ
SQL Serverがクエリをコンパイルまたは実行するたびに、メッセージがクエリストアに送信されます。これを次に示します。
コンパイルおよび実行情報は、クエリストアの構成に応じて、最初にメモリに保持されてからディスクに保存されます(データはINTERVAL_LENGTH_MINUTES
に従って集約されます。 パラメータ。デフォルトは1時間で、DATA_FLUSH_INTERVAL_SECONDS
に従ってディスクにフラッシュされます。 パラメータ)。システムにメモリ不足がある場合は、データをディスクにフラッシュすることもできます。いずれの場合も、sys.query_store_runtime_stats
を実行すると、メモリとディスクの両方のすべてのデータにアクセスできるようになります。 カタログ。
カタログ
収集されたデータはディスクに保持され、クエリストアが有効になっているユーザーデータベースに保存されます(設定はsys.database_query_store_options
に保存されます)。 。クエリストアのカタログは次のとおりです。
sys.query_store_query_text | クエリテキスト情報 |
sys.query_store_query | クエリテキストとSETオプションに影響する使用済みプラン |
sys.query_store_plan | 履歴を含む実行計画 |
sys.query_store_runtime_stats | クエリ実行時統計 |
sys.query_store_runtime_stats_interval | 間隔の開始時間と終了時間 |
sys.query_context_settings | クエリコンテキスト設定情報 |
ランタイム統計は、平均、最後、最小、最大、標準偏差など、多数のメトリックをキャプチャします。 sys.query_store_runtime_stats
の列の完全なセットは次のとおりです :
runtime_stats_id | plan_id | runtime_stats_interval_id | ||
execution_type | execution_type_desc | first_execution_time | last_execution_time | count_executions |
avg_duration | last_duration | min_duration | max_duration | stdev_duration |
avg_cpu_time | last_cpu_time | min_cpu_time | max_cpu_time | stdev_cpu_time |
avg_logical_io_reads | last_logical_io_reads | min_logical_io_reads | max_logical_io_reads | stdev_logical_io_reads |
avg_logical_io_writes | last_logical_io_writes | min_logical_io_writes | max_logical_io_writes | stdev_logical_io_writes |
avg_physical_io_reads | last_physical_io_reads | min_physical_io_reads | max_physical_io_reads | stdev_physical_io_reads |
avg_clr_time | last_clr_time | min_clr_time | max_clr_time | stdev_clr_time |
avg_dop | last_dop | min_dop | max_dop | stdev_dop |
avg_query_max_used_memory | last_query_max_used_memory | min_query_max_used_memory | max_query_max_used_memory | stdev_query_max_used_memory |
avg_rowcount | last_rowcount | min_rowcount | max_rowcount | stdev_rowcount |
sys.query_store_runtime_statsの列
このデータは、クエリの実行が終了したときにのみキャプチャされます。クエリストアは、クエリのSET
も考慮します オプション。最適化プロセス中に定数式を評価した結果などに影響するため、実行プランの選択に影響を与える可能性があります。このトピックについては、以前の投稿で取り上げました。
結論
これは間違いなく素晴らしい機能であり、できるだけ早く試してみたいものです(ちなみに、Conorのデモには「SQLServer 15 CTP1」が示されていますが、これらのビットは公開されていません)。クエリストアは、CU、サービスパック、またはSQL Serverバージョンなどのアップグレードに役立ちます。これは、クエリストアによって収集された情報を前後に分析して、クエリがリグレッションを起こしたかどうかを確認できるためです。 (この機能が下位エディションで利用できる場合は、SKUアップグレードシナリオでもこれを実行できます。)これを知っていると、問題に応じて特定のアクションを実行するのに役立ちます。これらの解決策の1つは、以前の計画を強制することです。前に説明したように。