実行中のストアドプロシージャを特定する1つの方法は、次のように「動的管理」メソッドを使用することです。
SELECT
sqlText.Text, req.*
FROM
sys.dm_exec_requests req
OUTER APPLY
sys.dm_exec_sql_text(req.sql_handle) AS sqltext
ただし、これは、ストアドプロシージャのcreateステートメントのテキストのみを表示します。例えば。:
CREATE PROCEDURE IMaProcedure @id int AS SELECT * FROM AllTheThings Where id = @id
理想的には、問題のある特定のパラメータセットに対して、実行中のプロシージャを長時間実行させる原因となっているプロシージャのパラメータを確認したいと思います。
それを行う方法はありますか? ( この質問Aaron Bertrand が DBCC InputBuffer について言及していますが、この問題には適切ではないと思います。)
この情報(ストアドプロシージャ(つまり、RPC呼び出し)またはパラメーター化されたクエリに渡されるランタイムパラメーター値)は、SQLトレースを介してのみ利用できます(SQL Serverの新しいバージョンでは、同等の拡張イベントを想定しています)。これは、SQL Serverプロファイラ(SQL Serverに付属)を実行し、RPC:Completed
、SP:Completed
、SQL:BatchCompleted
などのさまざまな「完了」イベントを選択することで確認できます。また、値がそこにあるので、「TextData」フィールドを選択する必要があります。
この質問に対する私の回答と@Kinの answer の違いは、@ Kinの回答(私が間違っている場合を除き、この場合は削除します)は次のいずれかを取得することに重点を置いていることです。
私の答えは、現在実行中のotherセッションのパラメーター値を取得することに焦点を当てています。 DMVに依存している場合、ランタイムパラメーター値がコンパイル済みパラメーター値と同じであるかどうかを知る方法はありません。この質問のコンテキストは、他のセッション/ SPIDを介して送信されるクエリの実行時の値を追跡することです(SQL Server 2005では拡張イベントがSQL Server 2008で導入されました)。
実際の実行プランをオンできる後、実行プランXMLを確認します。
または、 SQLセントリーのプランエクスプローラーツール を使用して、parameters
タブを表示し、compiled value
およびrun time value
実際の実行計画。
実際のプランをオンにするできない場合は、以下で説明するようにプランキャッシュを調べることができます。
-- borrowed from Erland Sommarskog
-- Link : http://www.sommarskog.se/query-plan-mysteries.html#dmvgettingplans
-- Remember that you are looking at the estimated plan so the actual no. of rows and actual executions wont be there ! <-- Important why a particular plan is bad.
DECLARE @dbname nvarchar(256),
@procname nvarchar(256)
SELECT @dbname = 'Northwind', -- Your DB name
@procname = 'dbo.List_orders_11' -- The SP that you want to get parameters for !
; WITH basedata AS (
SELECT qs.statement_start_offset/2 AS stmt_start,
qs.statement_end_offset/2 AS stmt_end,
est.encrypted AS isencrypted, est.text AS sqltext,
epa.value AS set_options, qp.query_plan,
charindex('<ParameterList>', qp.query_plan) + len('<ParameterList>')
AS paramstart,
charindex('</ParameterList>', qp.query_plan) AS paramend
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) est
CROSS APPLY sys.dm_exec_text_query_plan(qs.plan_handle,
qs.statement_start_offset,
qs.statement_end_offset) qp
CROSS APPLY sys.dm_exec_plan_attributes(qs.plan_handle) epa
WHERE est.objectid = object_id (@procname)
AND est.dbid = db_id(@dbname)
AND epa.attribute = 'set_options'
), next_level AS (
SELECT stmt_start, set_options, query_plan,
CASE WHEN isencrypted = 1 THEN '-- ENCRYPTED'
WHEN stmt_start >= 0
THEN substring(sqltext, stmt_start + 1,
CASE stmt_end
WHEN 0 THEN datalength(sqltext)
ELSE stmt_end - stmt_start + 1
END)
END AS Statement,
CASE WHEN paramend > paramstart
THEN CAST (substring(query_plan, paramstart,
paramend - paramstart) AS xml)
END AS params
FROM basedata
)
SELECT set_options AS [SET], n.stmt_start AS Pos, n.Statement,
CR.c.value('@Column', 'nvarchar(128)') AS Parameter,
CR.c.value('@ParameterCompiledValue', 'nvarchar(128)') AS [Sniffed Value],
CAST (query_plan AS xml) AS [Query plan]
FROM next_level n
CROSS APPLY n.params.nodes('ColumnReference') AS CR(c)
ORDER BY n.set_options, n.stmt_start, Parameter
@SolomonRutzkyは正しいです。
SQLプロファイラトレースが唯一の方法です(Sprocを編集せずに)。
ただし、次善の策は問題のSprocを少し編集することです。
DateTime変数を現在の時刻で最初に宣言します。
Sprocの最後に、Sproc_StartTime、Sproc_EndTime、およびパラメーター値をテーブルに記録します。
Sprocの処理に長い時間が使用された場合にのみ、ロギングにDateDiff()を使用する条件付きロジックを追加することもできます。
これにより、Sprocが高速化し、Sprocが最新の状態で実行されている場合のログテーブルのスペース消費量が削減されます。
次に、数か月かけてクエリを実行して分析できるログファイルがあります(製品でトレースを実行していません)。
Sprocの調整が完了したら、追加したタイマーおよびロガーロジックの数行を削除するだけです。
ログテーブルに現在のキャッシュプランのパラメーター値を含めると、パフォーマンスの問題を複雑にしているかどうかを判断するのに役立つことがあります。
私が使う OPTIMIZE FOR
は、データのスライスとダイシングに使用されることがわかっている場合に、Sprocでパラメーターを処理する方法を設定します。
私はOPTIMIZE FOR
は、パラメーターと同じSprocをオプションのフィルターとして使用すると、一貫した高速な結果を生成します。
それらの処理方法を指定する場合、考慮する変数が1つ少なくなることは間違いありません。
以下は、選択ステートメントの下部に追加する可能性のある例です。
OPTION(OPTIMIZE FOR (@SiteID = 'ABC',
@LocationID = NULL, @DepartmentID = NULL,
@EmployeeID = NULL, @CustomerID = NULL,
@ProductID = NULL, @OrderID = NULL, @OrderStatusID = NULL,
@IncludedCancelledOrders = 1,
@StartDate UNKNOWN, @EndDate UNKNOWN))
Erland Sommarskogのクエリを使用してプランXMLを細断し、ParameterCompiledValueを引き出すときに、最初の "basedata" CTEが[〜#〜] warnings [〜#〜](eg暗黙的)のプランを考慮していないことに気付きましたCHARINDEX(組み込み関数)が文字列入力(つまり)に一致する最初の式を検索するため、このような警告はこれらの同じフレーズ/ノードを使用します。
したがって、このセクションを以下の改訂されたセクションに置き換えることをお勧めします。
CHARINDEX('<ParameterList>', qp.query_plan) + LEN('<ParameterList>') AS paramstart,
CHARINDEX('</ParameterList>', qp.query_plan) AS paramend
改訂セクション:
CHARINDEX('<ParameterList><ColumnReference', qp.query_plan) + LEN('<ParameterList>') AS paramstart,
CHARINDEX('</ParameterList></QueryPlan>', qp.query_plan) AS paramend