SE の雑記

SQL Server の情報をメインに Microsoft 製品の勉強内容を日々投稿

待ち事象を時系列で解析するためのデータを取得する その 2

leave a comment

以前、待ち事象を時系列で解析するためのデータを取得する という投稿をしたのですがその別バージョンとなります。

以前の投稿は、定期的の wait_stats を取得していましたが、取得したタイミングの情報をそのまま格納していたため、右肩上がりの情報しか作成することができませんでした。

そこで以下のようなクエリを作成し、前回実行時との差分を求めてテーブルに格納する仕組みにしてみました。

SET NOCOUNT ON
GO
DECLARE @waittime nvarchar(8) = '00:00:10'
DECLARE @initilalize bit = 0
IF OBJECT_ID('tempdb..#tmp_wait_stats_old') IS NULL
BEGIN
	SELECT *
	INTO #tmp_wait_stats_old
	FROM sys.dm_os_wait_stats
	CREATE CLUSTERED INDEX IX_tmp_wait_stats_old
	ON #tmp_wait_stats_old (wait_type)
END
ELSE
BEGIN
	Truncate Table #tmp_wait_stats_old
END
IF OBJECT_ID('tempdb..#tmp_wait_stats') IS NULL
BEGIN
	SELECT
		GETDATE() AS DateTime,
		wait_type,
		waiting_tasks_count,
		wait_time_ms,
		max_wait_time_ms,
		signal_wait_time_ms
	INTO #tmp_wait_stats
	FROM sys.dm_os_wait_stats
	WHERE 1 = 0
	CREATE CLUSTERED INDEX IX_tmp_wait_stats
	ON #tmp_wait_stats (wait_type)
END
ELSE
BEGIN
	IF @initilalize = 1
		Truncate Table #tmp_wait_stats
END
WHILE (1=1)
BEGIN
	INSERT INTO
		#tmp_wait_stats
	SELECT
		GETDATE() AS DateTime,
		T1.wait_type,
		ISNULL(T1.waiting_tasks_count - T2.waiting_tasks_count, 0) AS waiting_tasks_count,
		ISNULL(T1.wait_time_ms - T2.wait_time_ms, 0) AS wait_time_ms,
		ISNULL(T1.max_wait_time_ms - T2.max_wait_time_ms, 0) AS max_wait_time_ms,
		ISNULL(T1.signal_wait_time_ms - T2.signal_wait_time_ms, 0) AS signal_wait_time_ms
	FROM
		sys.dm_os_wait_stats T1
		LEFT JOIN
		#tmp_wait_stats_old T2
		ON
			T1.wait_type = T2.wait_type
	ORDER BY
		T1.wait_type ASC
	TRUNCATE TABLE #tmp_wait_stats_old
	INSERT INTO  #tmp_wait_stats_old
	SELECT * FROM sys.dm_os_wait_stats
	EXEC ('WAITFOR DELAY ''' + @waittime + '''')
END

実行結果は、[#tmp_wait_stats] に格納されますので、実行後にこのテーブルを検索することで情報を確認することができます。

上記のクエリで 10 秒間隔で情報を取得している間に以下のクエリを SQLQueryStress で実行してみます。

SET NOCOUNT ON
DECLARE @delay int = (SELECT RAND() * 10)
EXEC ('WAITFOR DELAY ''00:00:' + @delay + '''')
WAITFOR DELAY '00:00:01'

image

以下は [WAITFOR] 待ち事象の情報を取得したものですが、このようなグラフを作成することができます。

image

格納先の一時テーブルを作成しない場合は以下のようなクエリでしょうか。

# 結果をファイルに保存して履歴を取得する必要がありますが。

SET NOCOUNT ON
GO
DECLARE @waittime nvarchar(8) = '00:00:10'
IF OBJECT_ID('tempdb..#tmp_wait_stats_old') IS NULL
BEGIN
	SELECT *
	INTO #tmp_wait_stats_old
	FROM sys.dm_os_wait_stats
	CREATE CLUSTERED INDEX IX_tmp_wait_stats_old
	ON #tmp_wait_stats_old (wait_type)
END
ELSE
BEGIN
	Truncate Table #tmp_wait_stats_old
END
WHILE (1=1)
BEGIN
	SELECT
		GETDATE() AS DateTime,
		T1.wait_type,
		ISNULL(T1.waiting_tasks_count - T2.waiting_tasks_count, 0) AS waiting_tasks_count,
		ISNULL(T1.wait_time_ms - T2.wait_time_ms, 0) AS wait_time_ms,
		ISNULL(T1.max_wait_time_ms - T2.max_wait_time_ms, 0) AS max_wait_time_ms,
		ISNULL(T1.signal_wait_time_ms - T2.signal_wait_time_ms, 0) AS signal_wait_time_ms
	FROM
		sys.dm_os_wait_stats T1
		LEFT JOIN
		#tmp_wait_stats_old T2
		ON
			T1.wait_type = T2.wait_type
	ORDER BY
		T1.wait_type ASC
	TRUNCATE TABLE #tmp_wait_stats_old
	INSERT INTO  #tmp_wait_stats_old
	SELECT * FROM sys.dm_os_wait_stats
	EXEC ('WAITFOR DELAY ''' + @waittime + '''')
END

今までは 2 点の差分しか出していなかったのですが、いろいろな確認方法を持っていたいなと。

Share

Written by Masayuki.Ozawa

6月 22nd, 2014 at 6:30 pm

Posted in SQL Server

Tagged with

Leave a Reply