ここからクエリを実行して、デフォルトの拡張イベントセッションからデッドロックイベントを引き出します。
SELECT CAST (
REPLACE (
REPLACE (
XEventData.XEvent.value ('(data/value)[1]', 'varchar(max)'),
'<victim-list>', '<deadlock><victim-list>'),
'<process-list>', '</victim-list><process-list>')
AS XML) AS DeadlockGraph
FROM (SELECT CAST (target_data AS XML) AS TargetData
FROM sys.dm_xe_session_targets st
JOIN sys.dm_xe_sessions s ON s.address = st.event_session_address
WHERE [name] = 'system_health') AS Data
CROSS APPLY TargetData.nodes ('//RingBufferTarget/event') AS XEventData (XEvent)
WHERE XEventData.XEvent.value('@name', 'varchar(4000)') = 'xml_deadlock_report';
私のマシンで完了するのに約20分かかります。報告される統計は
Table 'Worktable'. Scan count 0, logical reads 68121, physical reads 0, read-ahead reads 0,
lob logical reads 25674576, lob physical reads 0, lob read-ahead reads 4332386.
SQL Server Execution Times:
CPU time = 1241269 ms, elapsed time = 1244082 ms.
WHERE
句を削除すると、3,782行を返す1秒未満で完了します。
同様OPTION (MAXDOP 1)
に、元のクエリに追加すると、速度が大幅に低下し、lobの読み取りが大幅に少なくなります。
Table 'Worktable'. Scan count 0, logical reads 15, physical reads 0, read-ahead reads 0,
lob logical reads 6767, lob physical reads 0, lob read-ahead reads 6076.
SQL Server Execution Times:
CPU time = 639 ms, elapsed time = 693 ms.
だから私の質問は
誰が何が起こっているのか説明できますか?なぜ元の計画がこれほど壊滅的に悪化し、問題を回避する信頼できる方法があるのですか?
添加:
またINNER HASH JOIN
、DMVの結果が非常に小さいため、クエリを変更してある程度改善します(ただし、3分以上かかります)が、Joinタイプ自体が原因であるとは思わず、他の何かが変更されていると思われます。そのための統計
Table 'Worktable'. Scan count 0, logical reads 30294, physical reads 0, read-ahead reads 0,
lob logical reads 10741863, lob physical reads 0, lob read-ahead reads 4361042.
SQL Server Execution Times:
CPU time = 200914 ms, elapsed time = 203614 ms.
(拡張されたイベントリングバッファを充填した後DATALENGTH
のXML
4880045バイトであり、それは1,448のイベントを含んでいた。)でとすることなく、元のクエリのバージョンダウンカットをテストMAXDOP
ヒント。
SELECT COUNT(*)
FROM (SELECT CAST (target_data AS XML) AS TargetData
FROM sys.dm_xe_session_targets st
JOIN sys.dm_xe_sessions s
ON s.address = st.event_session_address
WHERE [name] = 'system_health') AS Data
CROSS APPLY TargetData.nodes ('//RingBufferTarget/event') AS XEventData (XEvent)
WHERE XEventData.XEvent.value('@name', 'varchar(4000)') = 'xml_deadlock_report'
SELECT*
FROM sys.dm_db_task_space_usage
WHERE session_id = @@SPID
次の結果を与えた
+-------------------------------------+------+----------+
| | Fast | Slow |
+-------------------------------------+------+----------+
| internal_objects_alloc_page_count | 616 | 1761272 |
| internal_objects_dealloc_page_count | 616 | 1761272 |
| elapsed time (ms) | 428 | 398481 |
| lob logical reads | 8390 | 12784196 |
+-------------------------------------+------+----------+
tempdbの割り当てには明らかな違いがあり、616
ページの割り当てと割り当て解除を示す高速な割り当てとは異なります。これは、XMLが変数に入れられるときに使用されるページと同じ量です。
遅いプランの場合、これらのページ割り当て数は数百万になります。dm_db_task_space_usage
クエリの実行中にポーリングを行うと、1,800〜3,000のページがtempdb
一度に割り当てられ、常にページの割り当てと割り当て解除が行われているようです。
WHERE
句をXQuery式に移動できます。高速化するためにロジックを削除する必要はありませんTargetData.nodes ('RingBufferTarget[1]/event[@name = "xml_deadlock_report"]')
。そうは言っても、私はあなたが提起した質問に答えるのに十分なほどXML内部を知らない。