SQL Serverのマルチステートメントストアドプロシージャのパフォーマンスの問題を修正しています。時間をかけるべき部分を知りたい。
私は クエリコストを読み取るにはどうすればよいですか、それは常にパーセンテージですか? SSMSが実際の実行プランを含めるに指示された場合でも、「クエリコスト(バッチ)」の数値は、コスト見積もりに基づいています。
私は クエリパフォーマンスの測定:「実行プランのクエリコスト」と「所要時間」 から、ストアドプロシージャの呼び出しをSET STATISTICS TIME
ステートメントで囲むことができることを理解し、次に、次のようなリストを取得します。これはMessages
ペインにあります:
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 1 ms.
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.
[etc]
SQL Server Execution Times:
CPU time = 187 ms, elapsed time = 206 ms.
ステートメントごとに1つの出力メッセージがあります。
「便利」ではありませんが、(簡単ではありませんが)時間統計出力を実行プランペインのステートメントごとの実行プランにカウントして関連付けることができます。4番目のSQL Server Execution Times
メッセージ出力はQuery 4
に対応します実行計画ペインなどで。
しかし、もっと良い方法はありますか?
Management Studioのプランでこれを行う方法はわかりませんが、これは、ツール内から実際のプランを生成するときに無料のSQL Sentry Plan Explorerが実行する多くの機能の1つです。ステートメントごとのランタイムメトリック。
http://sqlsentry.net/plan-Explorer/sql-server-query-view.asp
免責事項:私はSQL Sentryで働いています。
これを行う1つの良い方法は、プロファイラーを使用することです。開発用またはテスト用のボックスで問題のあるプロシージャの「再現」を設定します。つまり、パラメータを使用してプロシージャへのサンプル呼び出しを行います。次に、プロファイラーを使用して、TSQL_SPsテンプレートを使用してトレースを作成するか、空のテンプレートからSP:StmtCompletedイベントを追加します。まだ利用できない場合は、Duration、Reads、Writes、CPU列を追加します。 SPIDのトレースにフィルターを追加します(これはManagement Studioから知っておく必要があります)。また、Durationにフィルターを追加することもできます(たとえば、1000より大きい= 1秒より大きい)。
オーバーヘッドはありますがプロファイラーでトレースを実行する(プロダクションボックスでは行わないでください)か、定義をエクスポートしてサーバー側のトレースを作成できます。プロファイラーのオーバーヘッドは、専用の開発ボックスやテストボックスではそれほど重要ではありません。
プロシージャを実行して完了させます。この時点で実際の実行計画を収集することもできます。
トレースを停止してファイルを開くと、各ステップのタイミングを含む、プロシージャの行ごとの内訳が表示されます。これは、ボトルネックを特定するための計画よりも有用であると思いますが、調整する関連セクションを見ると計画が重宝します。
HTH
sys.dm_exec_procedure_stats および sys.dm_exec_query_stats 動的管理ビューを使用することもできます。それらの最初のものは、手順全体に関する情報を提供します。 2番目は、プロシージャ内の各クエリを分割するために使用できます。以下に例を示します。
USE AdventureWorks;
GO
CREATE PROCEDURE dbo.Test
@NameLike nvarchar(50)
AS
BEGIN
SELECT
ProductCount = COUNT_BIG(*)
FROM Production.Product AS p
JOIN Production.TransactionHistory AS th ON
th.ProductID = p.ProductID
WHERE
p.Name LIKE @NameLike;
SELECT
pc.Name,
ProductCount = COUNT_BIG(*)
FROM Production.Product AS p
JOIN Production.ProductSubcategory AS ps ON
ps.ProductSubcategoryID = p.ProductSubcategoryID
JOIN Production.ProductCategory AS pc ON
pc.ProductCategoryID = ps.ProductCategoryID
WHERE
p.Name LIKE @NameLike
GROUP BY
pc.Name
ORDER BY
pc.Name;
END;
GO
EXECUTE dbo.Test @NameLike = N'A%';
EXECUTE dbo.Test @NameLike = N'F%';
手順の統計:
SELECT
deps.last_execution_time,
deps.last_worker_time,
deps.last_physical_reads,
deps.last_logical_writes,
deps.last_logical_reads,
deps.last_elapsed_time
FROM sys.dm_exec_procedure_stats AS deps
WHERE
deps.database_id = DB_ID()
AND deps.[object_id] = OBJECT_ID(N'dbo.Test', N'P');
プロシージャ内のクエリ:
SELECT
query.the_text,
deqs.last_execution_time,
deqs.last_worker_time,
deqs.last_physical_reads,
deqs.last_logical_writes,
deqs.last_logical_reads,
deqs.last_clr_time,
deqs.last_elapsed_time,
deqs.last_rows -- note: Only present from 2008 R2 onwards
FROM sys.dm_exec_query_stats AS deqs
CROSS APPLY sys.dm_exec_sql_text(deqs.[sql_handle]) AS dest
CROSS APPLY
(
VALUES
(
SUBSTRING
(
dest.[text],
deqs.statement_start_offset / 2 + 1,
(ISNULL(NULLIF(deqs.statement_end_offset, -1), DATALENGTH(dest.[text])) - deqs.statement_start_offset) / 2 + 1
)
)
) AS query (the_text)
WHERE
deqs.[sql_handle] IN
(
SELECT
deps.[sql_handle]
FROM sys.dm_exec_procedure_stats AS deps
WHERE
deps.database_id = DB_ID()
AND deps.[object_id] = OBJECT_ID(N'dbo.Test', N'P')
);