SQL Serverでクエリ実行プランを取得するにはどうすればよいですか?


338

Microsoft SQL Serverで、クエリ/ストアドプロシージャのクエリ実行プランを取得するにはどうすればよいですか?


2
SQL Server Management Studioの[実行プラン]タブを閉じるにはどうすればよいですか?
ポール・マッカーシー

2
@Paul Ctrl + Rを押すことができます。メッセージと実行プランを含む、結果セクション全体を閉じます。
Nisarg 2018年

回答:


500

実行プランを取得する方法はいくつかありますが、使用する方法は状況によって異なります。通常、SQL Server Management Studioを使用して計画を取得できますが、何らかの理由でSQL Server Management Studioでクエリを実行できない場合は、SQL Server Profilerまたは検査によって計画を取得できると便利です。計画キャッシュ。

方法1-SQL Server Management Studioを使用する

SQL Serverには、実行計画を非常に簡単に取得できる2つの優れた機能が備わっています。[クエリ]メニューにある[実際の実行計画を含める]メニュー項目がチェックされていることを確認し、通常どおりにクエリを実行します。 。

[アクション実行プランを含める]メニュー項目

ストアドプロシージャのステートメントの実行プランを取得しようとしている場合は、次のようにストアドプロシージャを実行する必要があります。

exec p_Example 42

クエリが完了すると、結果ペインに「実行計画」というタイトルの追加のタブが表示されます。多くのステートメントを実行した場合、このタブに多くのプランが表示されることがあります。

実行計画のスクリーンショット

ここから、SQL Server Management Studioで実行プランを検査するか、プランを右クリックして[名前を付けて実行プランを保存...]を選択して、プランをXML形式のファイルに保存できます。

方法2-SHOWPLANオプションの使用

この方法は方法1と非常によく似ています(実際、これはSQL Server Management Studioが内部で行うことです)。

クエリを実行する前に、次のいずれかのステートメントを実行します。ステートメントはバッチ内の唯一のステートメントでなければなりません。つまり、同時に別のステートメントを実行することはできません。

SET SHOWPLAN_TEXT ON
SET SHOWPLAN_ALL ON
SET SHOWPLAN_XML ON
SET STATISTICS PROFILE ON
SET STATISTICS XML ON -- The is the recommended option to use

これらは接続オプションであるため、接続ごとに1回だけ実行する必要があります。この時点から、実行されるすべてのステートメントには、目的の形式の実行プランを含む追加の結果セットが付随します。通常、プランを表示するのと同じようにクエリを実行するだけです。

完了したら、次のステートメントでこのオプションをオフにできます。

SET <<option>> OFF

実行計画形式の比較

あなたが強い好みがない限り、私の推奨はSTATISTICS XMLオプションを使用することです。このオプションは、SQL Server Management Studioの[実際の実行計画を含める]オプションと同等であり、最も便利な形式でほとんどの情報を提供します。

  • SHOWPLAN_TEXT -クエリを実行せずに、基本的なテキストベースの推定実行プランを表示します
  • SHOWPLAN_ALL -クエリを実行せずに、テキストベースの推定見積もりとコスト見積もりを表示します
  • SHOWPLAN_XML-クエリを実行せずに、XMLベースの推定見積もりとコスト見積もりを表示します。これは、SQL Server Management Studioの[推定実行プランの表示...]オプションに相当します。
  • STATISTICS PROFILE -クエリを実行し、テキストベースの実際の実行プランを表示します。
  • STATISTICS XML-クエリを実行し、XMLベースの実際の実行プランを表示します。これは、SQL Server Management Studioの[実際の実行プランを含める]オプションに相当します。

方法3-SQL Serverプロファイラーを使用する

クエリを直接実行できない場合(またはクエリを直接実行しても速度が低下しない場合-クエリの実行計画が適切でないことを思い出してください)、SQL Serverプロファイラートレースを使用して計画をキャプチャできます。アイデアは、 "Showplan"イベントの1つをキャプチャしているトレースの実行中にクエリを実行することです。

負荷によっては、本番環境でこの方法を使用できます、注意が必要なことは明らかです。SQL Serverのプロファイリングのメカニズムは、データベースへの影響を最小限に抑えるように設計されているが、これはそこにないことを意味するものではありません任意のパフォーマンスへの影響。データベースが頻繁に使用されている場合、トレースで正しいプランをフィルタリングおよび特定する際に問題が発生する場合もあります。DBAが貴重なデータベースでこれを行って満足しているかどうかは、DBAに明らかに確認する必要があります。

  1. SQL Serverプロファイラーを開き、トレースを記録する対象のデータベースに接続する新しいトレースを作成します。
  2. [イベントの選択]タブで、[すべてのイベントを表示]をオンにし、[パフォーマンス]-> [XMLを表示]行をオンにして、トレースを実行します。
  3. トレースの実行中に、実行速度の遅いクエリを実行するために必要なことをすべて実行します。
  4. クエリが完了するまで待ち、トレースを停止します。
  5. トレースを保存するには、SQL Serverプロファイラーでプランxmlを右クリックし、[イベントデータの抽出...]を選択して、プランをXML形式でファイルに保存します。

取得するプランは、SQL Server Management Studioの[実際の実行プランを含める]オプションと同等です。

方法4-クエリキャッシュを検査する

クエリを直接実行できず、プロファイラートレースもキャプチャできない場合でも、SQLクエリプランのキャッシュを調べることにより、推定プランを取得できます。

SQL Server DMVにクエリを実行して、プランキャッシュを検査します。以下は、すべてのキャッシュされたクエリプランを(xmlとして)SQLテキストとともに一覧表示する基本的なクエリです。ほとんどのデータベースでは、関心のある計画だけに結果を絞り込むために、追加のフィルター句を追加する必要があります。

SELECT UseCounts, Cacheobjtype, Objtype, TEXT, query_plan
FROM sys.dm_exec_cached_plans 
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
CROSS APPLY sys.dm_exec_query_plan(plan_handle)

このクエリを実行し、プランXMLをクリックしてプランを新しいウィンドウで開きます。右クリックして[名前を付けて実行プランを保存...]を選択し、プランをXML形式でファイルに保存します。

ノート:

非常に多くの要因が関与しているため(テーブルやインデックススキーマから、格納されているデータやテーブルの統計に至るまで)、関心のあるデータベース(通常、パフォーマンスが発生しているもの)から実行プランを取得するように常に心がける必要があります。問題)。

暗号化されたストアドプロシージャの実行プランはキャプチャできません。

「実際」と「推定」の実行計画

実際の実行計画は、一方でSQL Serverが実際に、クエリを実行1であると推定実行計画SQL Serverは、それがどのようなうまくいくでしょうクエリを実行せずに行います。論理的には同等ですが、実際の実行プランには、クエリの実行時に実際に何が起こったかに関する詳細と統計が含まれているため、はるかに便利です。これは、SQL Serverの見積もりがオフになっている問題(統計が古くなっている場合など)を診断する場合に不可欠です。

クエリ実行プランを解釈するにはどうすればよいですか?

これは、それだけで(無料の)として十分価値のあるトピックです。

以下も参照してください。


8
今後の読者への注意:SET STATISTICS XML ONクエリの最初と、計画の出力に表示したくないSET STATISTICS XML OFF|ON周辺領域を入力してください:クエリに不要な反復(WHILE)が含まれている場合に、これが便利です。実行プランで確認します(そうしないと、SQL SERVERで表示するには重すぎて長くなります。
Roimer 2013年

2
@MonsterMMORPGでは、方法4を使用してからSELECTできます。たとえば、<a href=" github.com/StackExchange/dapper-dot-net"> Dapper.net </… > connection.Query <string>( "SELECT query_plan FROM sys.dm_exec_cached_plans CROSS APPLY sys.dm_exec_sql_text(plan_handle )CROSS APPLY sys.dm_exec_query_plan(plan_handle)WHERE TEXT LIKE N '%Your Original Query Goes Here%' "); %は、クエリのサブセットのみを使用する場合です。
bmarks 2015

2
@Justinは、クエリの実行計画を解釈するためにリンクした本の第2版の日付が2009年であるとします。それでも、2016年にはその目的のための本当に良いリソースだと思いますか?
Abdul

3
@Abdul同じ作者のGrant Fritcheyが、SQL Serverの新しいバージョンをカバーするSQL Server Query Performance Tuningと呼ばれる新しい本を持っています。
thelem

42

すでに投稿されている包括的な回答に加えて、実行計画にプログラムからアクセスして情報を抽出できると便利な場合があります。これのサンプルコードは以下です。

DECLARE @TraceID INT
EXEC StartCapture @@SPID, @TraceID OUTPUT
EXEC sp_help 'sys.objects' /*<-- Call your stored proc of interest here.*/
EXEC StopCapture @TraceID

StartCapture定義の例

CREATE PROCEDURE StartCapture
@Spid INT,
@TraceID INT OUTPUT
AS
DECLARE @maxfilesize BIGINT = 5
DECLARE @filepath NVARCHAR(200) = N'C:\trace_' + LEFT(NEWID(),36)

EXEC sp_trace_create @TraceID OUTPUT, 0, @filepath, @maxfilesize, NULL 

exec sp_trace_setevent @TraceID, 122, 1, 1
exec sp_trace_setevent @TraceID, 122, 22, 1
exec sp_trace_setevent @TraceID, 122, 34, 1
exec sp_trace_setevent @TraceID, 122, 51, 1
exec sp_trace_setevent @TraceID, 122, 12, 1
-- filter for spid
EXEC sp_trace_setfilter @TraceID, 12, 0, 0, @Spid
-- start the trace
EXEC sp_trace_setstatus @TraceID, 1

StopCapture定義の例

CREATE  PROCEDURE StopCapture
@TraceID INT
AS
WITH  XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/2004/07/showplan' as sql), 
      CTE
     as (SELECT CAST(TextData AS VARCHAR(MAX)) AS TextData,
                ObjectID,
                ObjectName,
                EventSequence,
                /*costs accumulate up the tree so the MAX should be the root*/
                MAX(EstimatedTotalSubtreeCost) AS EstimatedTotalSubtreeCost
         FROM   fn_trace_getinfo(@TraceID) fn
                CROSS APPLY fn_trace_gettable(CAST(value AS NVARCHAR(200)), 1)
                CROSS APPLY (SELECT CAST(TextData AS XML) AS xPlan) x
                CROSS APPLY (SELECT T.relop.value('@EstimatedTotalSubtreeCost',
                                            'float') AS EstimatedTotalSubtreeCost
                             FROM   xPlan.nodes('//sql:RelOp') T(relop)) ca
         WHERE  property = 2
                AND TextData IS NOT NULL
                AND ObjectName not in ( 'StopCapture', 'fn_trace_getinfo' )
         GROUP  BY CAST(TextData AS VARCHAR(MAX)),
                   ObjectID,
                   ObjectName,
                   EventSequence)
SELECT ObjectName,
       SUM(EstimatedTotalSubtreeCost) AS EstimatedTotalSubtreeCost
FROM   CTE
GROUP  BY ObjectID,
          ObjectName  

-- Stop the trace
EXEC sp_trace_setstatus @TraceID, 0
-- Close and delete the trace
EXEC sp_trace_setstatus @TraceID, 2
GO

18

Microsoft SQL Server Management Studioを使用していると仮定

  • 以下のための推定クエリプランあなたは押すことができますCtrlキー+ Lまたは以下のボタンを。

ここに画像の説明を入力してください

  • 以下のために実際のクエリ・プラン、あなたは押すことができますCtrlキー+ Mまたはクエリを実行する前に、以下のボタンを。

ここに画像の説明を入力してください

  • 以下のためにライブクエリプラン(のみSSMS 2016年)、クエリを実行する前に、次のボタンを使用します。

ここに画像の説明を入力してください


15

前の回答で説明した方法のほかに、無料の実行プランビューアとクエリ最適化ツールApexSQLプランを使用することもできます(最近。

ApexSQLプランをインストールしてSQL Server Management Studioに統合できるため、実行プランをSSMSから直接表示できます。

ApexSQLプランでの推定実行プランの表示

  1. SSMSで[ 新しいクエリ ]ボタンをクリックし、クエリテキストウィンドウにクエリテキストを貼り付けます。右クリックして、コンテキストメニューから[推定実行プランの表示]オプションを選択します。

SSMSの新しいクエリボタン

  1. 実行計画図は、結果セクションの[実行計画]タブに表示されます。次に、実行プランを右クリックし、コンテキストメニューで[ApexSQLプランで開く]オプションを選択します。

実行計画

  1. 推定実行プランがApexSQLプランで開かれ、クエリの最適化のために分析できます。

推定実行計画

ApexSQLプランでの実際の実行プランの表示

クエリの実際の実行プランを表示するには、前述の2番目のステップから続行しますが、今度は推定プランが表示されたら、ApexSQLプランのメインリボンバーから[実際]ボタンをクリックします。

メインリボンバーの[実際]ボタンをクリックします

「実際」ボタンをクリックすると、実際の実行プランが表示され、他の実行プランデータとともにコストパラメータの詳細なプレビューが表示されます。

実際の実行計画

実行プランの表示の詳細については、このリンクをクリックしてください


14

クエリ実行プランを取得して詳細に分析するための私のお気に入りのツールは、SQL Sentry Plan Explorerです。です。これは、SSMSよりも実行計画の詳細分析と視覚化に関して、はるかにユーザーフレンドリーで便利で包括的なものです。

ツールが提供する機能を理解するためのスクリーンショットの例を以下に示します。

SQL Sentry Plan Explorerウィンドウのスクリーンショット

ツールで使用できるビューの1つにすぎません。アプリウィンドウの下部にある一連のタブに注目してください。これを使用すると、さまざまなタイプの実行プランの表現と役立つ追加情報を取得できます。

さらに、私はその無料版が日常的にそれを使用することを妨げる、またはあなたが最終的にプロ版を購入することを強いる制限に気づいていません。したがって、無料版を使い続けることを希望する場合は、そうすることを禁じるものはありません。

更新:Martin Smithに感謝)Plan Explorerが無料になりました!詳細については、http://www.sqlsentry.com/products/plan-explorer/sql-server-query-viewを参照してください。


1
サードパーティのツールについては誰が話していましたか?
バッシャー

12
@basher:OPは、MSツールなどで手段を制限しませんでした。では、サードパーティのツールを含む回答は不適切なものだと思う理由は何ですか?
Alexander Abakumov、2015

3
Speaking of third-party toolsサードパーティのツールについて誰も言及しなかったとき、あなたが答えの始まりをどのように言ったかで冗談を言っていました。
バッシャー

4
@バッシャー:ああ、いいキャッチ!ありがとうございました!回答を書き直しました。必要に応じて、フィードバックや投票にご遠慮なくお問い合わせください。
Alexander Abakumov

3
ところで、現在は1つのバージョンしかありませんsqlsentry.com/products/plan-explorer/sql-server-query-view
Martin Smith

7

クエリプランは、query_post_execution_showplanイベントを介して拡張イベントセッションから取得できます。次にXEventセッションの例を示します。

/*
    Generated via "Query Detail Tracking" template.
*/
CREATE EVENT SESSION [GetExecutionPlan] ON SERVER 
ADD EVENT sqlserver.query_post_execution_showplan(
    ACTION(package0.event_sequence,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)),

/* Remove any of the following events (or include additional events) as desired. */
ADD EVENT sqlserver.error_reported(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.module_end(SET collect_statement=(1)
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.rpc_completed(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.sp_statement_completed(SET collect_object_name=(1)
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.sql_batch_completed(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.sql_statement_completed(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))) 
ADD TARGET package0.ring_buffer
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF)
GO

セッションを作成したら、(SSMSで)オブジェクトエクスプローラーに移動し、[管理]、[詳細]の順に進みます。拡張イベント| セッション。「GetExecutionPlan」セッションを右クリックして開始します。もう一度右クリックして、[ライブデータを見る]を選択します。

次に、新しいクエリウィンドウを開き、1つ以上のクエリを実行します。以下は、AdventureWorksの1つです。

USE AdventureWorks;
GO

SELECT p.Name AS ProductName, 
    NonDiscountSales = (OrderQty * UnitPrice),
    Discounts = ((OrderQty * UnitPrice) * UnitPriceDiscount)
FROM Production.Product AS p 
INNER JOIN Sales.SalesOrderDetail AS sod
    ON p.ProductID = sod.ProductID 
ORDER BY ProductName DESC;
GO

しばらくすると、[GetExecutionPlan:ライブデータ]タブに結果が表示されます。グリッドでいずれかのquery_post_execution_showplanイベントをクリックし、グリッドの下にある[クエリプラン]タブをクリックします。これは次のようになります。

ここに画像の説明を入力してください

編集:XEventコードとスクリーンショットは、SQL / SSMS 2012 w / SP2から生成されました。SQL 2008 / R2を使用している場合は、スクリプトを微調整して実行することができる場合あります。ただし、そのバージョンにはGUIがないため、プラン表示XMLを抽出し、*。sqlplanファイルとして保存して、SSMSで開く必要があります。それは面倒です。XEventsはSQL 2005以前には存在しませんでした。したがって、SQL 2012以降を使用していない場合は、ここに掲載されている他の回答の1つを強くお勧めします。


5

SQL Server 2016以降、パフォーマンスを監視するためのクエリストア機能が導入されました。クエリプランの選択とパフォーマンスに関する洞察を提供します。これは、トレースイベントや拡張イベントの完全な置き換えではありませんが、バージョンごとに進化しているため、SQL Serverの将来のリリースでは、完全に機能するクエリストアを取得する可能性があります。クエリストアの主要なフロー

  1. SQL Serverの既存のコンポーネントは、クエリストアマネージャーを利用してクエリストアとやり取りします。
  2. クエリストアマネージャーは、使用するストアを決定し、そのストアに実行を渡します(計画またはランタイム統計またはクエリ待機統計)
    • プランストア-実行プラン情報の永続化
    • ランタイム統計ストア-実行統計情報の永続化
    • クエリ待機統計ストア-永続的な待機統計情報。
  3. 計画、実行時統計、待機ストアは、SQL Serverの拡張機能としてクエリストアを使用します。

ここに画像の説明を入力してください

  1. クエリストアの有効化:クエリストアは、サーバーのデータベースレベルで機能します。

    • クエリストアは、デフォルトでは新しいデータベースに対してアクティブではありません。
    • マスターまたはtempdbデータベースのクエリストアを有効にすることはできません。
    • 利用可能なDMV

      sys.database_query_store_options (Transact-SQL)

  2. クエリストアでの情報の収集:クエリストアDMV(データ管理ビュー)を使用して、3つのストアからすべての利用可能な情報を収集します。

    • クエリプランストア: 実行プラン情報を保持し、クエリのコンパイルに関連するすべての情報を取得する責任があります。

      sys.query_store_query(Transact-SQL) sys.query_store_plan(Transact-SQL) sys.query_store_query_text(Transact-SQL)

    • ランタイム統計ストア: 実行統計情報を保持しており、おそらく最も頻繁に更新されるストアです。これらの統計はクエリ実行データを表します。

      sys.query_store_runtime_stats (Transact-SQL)

    • クエリ待機統計ストア: 待機統計情報の永続化とキャプチャ。

      sys.query_store_wait_stats (Transact-SQL)

注:クエリ待機統計ストアは、SQL Server 2017以降でのみ使用できます


4

SQL Server Management Studio(説明済み)と同様に、ここで説明するようにDatagripでも可能です

  1. SQLステートメントを右クリックして、「プランの説明」を選択します。
  2. [出力]ウィンドウで、[計画]をクリックします。
  3. デフォルトでは、クエリのツリー表現が表示されます。クエリプランを表示するには、[視覚化の表示]アイコンをクリックするか、Ctrl + Shift + Alt + Uを押します。

3

これまでに述べたことすべてに加えて、知っておくべき重要なことが1つあります。

多くの場合、クエリプランは複雑すぎて、ネストされた要素のレベル127に制限されている組み込みのXML列タイプで表すことができません。これが、以前のMS SQLバージョンでsys.dm_exec_query_planNULLエラーを返す、またはエラーをスローする理由の1つであるため、通常は代わりにsys.dm_exec_text_query_planを使用する方が安全です。後者には、バッチ全体ではなく特定のステートメントのプランを選択するという便利なボーナス機能もあります。これを使用して、現在実行中のステートメントのプランを表示する方法は次のとおりです。

SELECT p.query_plan
FROM sys.dm_exec_requests AS r
OUTER APPLY sys.dm_exec_text_query_plan(
                r.plan_handle,
                r.statement_start_offset,
                r.statement_end_offset) AS p

ただし、結果のテーブルのテキスト列は、XML列と比較するとあまり便利ではありません。結果をクリックしてダイアグラムとして別のタブで開くことができるようにするには、その内容をファイルに保存する必要はありませんが、ちょっとしたトリックを使用できます(を使用できないことに注意してくださいCAST(... AS XML))。これは、単一行:

SELECT Tag = 1, Parent = NULL, [ShowPlanXML!1!!XMLTEXT] = query_plan
FROM sys.dm_exec_text_query_plan(
                -- set these variables or copy values
                -- from the results of the above query
                @plan_handle,
                @statement_start_offset,
                @statement_end_offset)
FOR XML EXPLICIT

2

この記事で説明したように、SQL Serverを使用すると、2種類の実行プランを取得できます。

推定実行計画

推定実行プランは、SQLクエリを実行せずにオプティマイザーによって生成されます。

推定実行プランを取得するには、 SHOWPLAN_ALLするには、クエリを実行する前に設定ます。

SHOWPLAN_ALLをオンに設定

ここで、次のSQLクエリを実行すると、

SELECT p.id
FROM post p
WHERE EXISTS (
  SELECT 1
  FROM post_comment pc
  WHERE
    pc.post_id = p.id AND
    pc.review = 'Bingo'
)
ORDER BY p.title
OFFSET 20 ROWS
FETCH NEXT 10 ROWS ONLY

SQL Serverは、次の推定実行プランを生成します。

| NodeId | Parent | LogicalOp            | EstimateRows | EstimateIO  | EstimateCPU | AvgRowSize | TotalSubtreeCost | EstimateExecutions |
|--------|--------|----------------------|--------------|-------------|-------------|------------|------------------|--------------------|
| 1      | 0      | NULL                 | 10           | NULL        | NULL        | NULL       | 0.03374284       | NULL               |
| 2      | 1      | Top                  | 10           | 0           | 3.00E-06    | 15         | 0.03374284       | 1                  |
| 4      | 2      | Distinct Sort        | 30           | 0.01126126  | 0.000504114 | 146        | 0.03373984       | 1                  |
| 5      | 4      | Inner Join           | 46.698       | 0           | 0.00017974  | 146        | 0.02197446       | 1                  |
| 6      | 5      | Clustered Index Scan | 43           | 0.004606482 | 0.0007543   | 31         | 0.005360782      | 1                  |
| 7      | 5      | Clustered Index Seek | 1            | 0.003125    | 0.0001581   | 146        | 0.0161733        | 43                 |

推定実行プランの取得に関心のあるクエリを実行した後、SHOWPLAN_ALLas を無効にする必要があります。無効にしないと、現在のデータベースセッションは、提供されたSQLクエリを実行するのではなく、推定実行プランのみを生成します。

SET SHOWPLAN_ALL OFF

SQL Server Management Studioの推定計画

SQL Server Management Studioアプリケーションでは、CTRL+Lキーショートカットを押すことで、SQLクエリの推定実行プランを簡単に取得できます。

ここに画像の説明を入力してください

実際の実行計画

実際のSQL実行プランは、SQLクエリの実行時にオプティマイザーによって生成されます。データベーステーブルの統計が正確である場合、実際の計画は推定されたものと大幅に異なるべきではありません。

SQL Serverで実際の実行プランを取得するにはSTATISTICS IO, TIME, PROFILE、次のSQLコマンドで示されているように、設定を有効にする必要があります。

SET STATISTICS IO, TIME, PROFILE ON

ここで、前のクエリを実行すると、SQL Serverは次の実行プランを生成します。

| Rows | Executes | NodeId | Parent | LogicalOp            | EstimateRows | EstimateIO  | EstimateCPU | AvgRowSize | TotalSubtreeCost |
|------|----------|--------|--------|----------------------|--------------|-------------|-------------|------------|------------------|
| 10   | 1        | 1      | 0      | NULL                 | 10           | NULL        | NULL        | NULL       | 0.03338978       |
| 10   | 1        | 2      | 1      | Top                  | 1.00E+01     | 0           | 3.00E-06    | 15         | 0.03338978       |
| 30   | 1        | 4      | 2      | Distinct Sort        | 30           | 0.01126126  | 0.000478783 | 146        | 0.03338679       |
| 41   | 1        | 5      | 4      | Inner Join           | 44.362       | 0           | 0.00017138  | 146        | 0.02164674       |
| 41   | 1        | 6      | 5      | Clustered Index Scan | 41           | 0.004606482 | 0.0007521   | 31         | 0.005358581      |
| 41   | 41       | 7      | 5      | Clustered Index Seek | 1            | 0.003125    | 0.0001581   | 146        | 0.0158571        |

SQL Server parse and compile time:
   CPU time = 8 ms, elapsed time = 8 ms.

(10 row(s) affected)
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'post'. Scan count 0, logical reads 116, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'post_comment'. Scan count 1, logical reads 5, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(6 row(s) affected)

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 1 ms.

実際の実行プランを取得することに関心のあるクエリを実行した後、次のSTATISTICS IO, TIME, PROFILE ONような設定を無効にする必要があります。

SET STATISTICS IO, TIME, PROFILE OFF

SQL Server Management Studioの実際の計画

SQL Server Management Studioアプリケーションでは、CTRL+Mキーショートカットを押すことで、SQLクエリの推定実行プランを簡単に取得できます。

ここに画像の説明を入力してください

SQL Serverを使用する場合の実行プランの取得について詳しくは、こちらの記事をご覧ください。


2

また、SET STATISTICS XML ONを使用してpowershellから実行し、実際の計画を取得することもできます。複数ステートメントのプランを1つのプランにマージするように記述しました。

    ########## BEGIN : SCRIPT VARIABLES #####################
    [string]$server = '.\MySQLServer'
    [string]$database = 'MyDatabase'
    [string]$sqlCommand = 'EXEC sp_ExampleSproc'
    [string]$XMLOutputFileName = 'sp_ExampleSproc'
    [string]$XMLOutputPath = 'C:\SQLDumps\ActualPlans\'
    ########## END   : SCRIPT VARIABLES #####################

    #Set up connection
    $connectionString = "Persist Security Info=False;Integrated Security=true;Connection Timeout=0;Initial Catalog=$database;Server=$server"
    $connection = new-object system.data.SqlClient.SQLConnection($connectionString)

    #Set up commands
    $command = new-object system.data.sqlclient.sqlcommand($sqlCommand,$connection)
    $command.CommandTimeout = 0
    $commandXMLActPlanOn = new-object system.data.sqlclient.sqlcommand("SET STATISTICS XML ON",$connection)
    $commandXMLActPlanOff = new-object system.data.sqlclient.sqlcommand("SET STATISTICS XML OFF",$connection)

    $connection.Open()

    #Enable session XML plan
    $result = $commandXMLActPlanOn.ExecuteNonQuery()

    #Execute SP and return resultsets into a dataset
    $adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
    $dataset = New-Object System.Data.DataSet
    $adapter.Fill($dataSet) | Out-Null

    #Set up output file name and path
    [string]$fileNameDateStamp = get-date -f yyyyMMdd_HHmmss
    [string]$XMLOutputFilePath = "$XMLOutputPath$XMLOutputFileName`_$fileNameDateStamp.sqlplan"

    #Pull XML plans out of dataset and merge into one multi-statement plan
    [int]$cntr = 1
    ForEach($table in $dataset.Tables)
    {
            if($table.Columns[0].ColumnName -eq "Microsoft SQL Server 2005 XML Showplan")
            {

                [string]$fullXMLPlan = $Table.rows[0]."Microsoft SQL Server 2005 XML Showplan"

                if($cntr -eq 1)
                    {

                    [regex]$rx = "\<ShowPlanXML xmlns\=.{1,}\<Statements\>"
                    [string]$startXMLPlan = $rx.Match($fullXMLPlan).Value
                    [regex]$rx = "\<\/Statements\>.{1,}\<\/ShowPlanXML\>"
                    [string]$endXMLPlan = $rx.Match($fullXMLPlan).Value

                    $startXMLPlan | out-file -Append -FilePath $XMLOutputFilePath

                    }

                [regex]$rx = "\<StmtSimple.{1,}\<\/StmtSimple\>"
                [string]$bodyXMLPlan = $rx.Match($fullXMLPlan).Value

                $bodyXMLPlan | out-file -Append -FilePath $XMLOutputFilePath

                $cntr += 1
            } 
    }

    $endXMLPlan | out-file -Append -FilePath $XMLOutputFilePath

    #Disable session XML plan
    $result = $commandXMLActPlanOff.ExecuteNonQuery()

    $connection.Close()

0

実行プランの説明は非常に詳細であり、かなりの読み取り時間を要しますが、要約すると、クエリの前に「説明」を使用すると、最初に実行された部分などの多くの情報が得られます。これについてもう少し詳しく知りたい場合は、これについての小さなブログをまとめました。これにより、正しい参照先も示されます。 https://medium.com/swlh/jetbrains-datagrip-explain-plan-ac406772c470

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.