여기에서 쿼리를 실행 하여 기본 확장 이벤트 세션에서 교착 상태 이벤트를 가져옵니다.
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)
원래 쿼리에 추가 하면 통계가 훨씬 적은 수의 로브 읽기를 표시하여 속도가 향상됩니다.
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
4,880,045 바이트이고 그것이 1448 이벤트가 포함되어 있습니다.)과 함께 그리고없이 원래 쿼리의 버전 아래로 상처를 테스트 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 |
+-------------------------------------+------+----------+
616
페이지가 빠르게 할당되고 할당이 해제되는 것을 보여주는 tempdb 할당에는 분명한 차이가 있습니다. XML도 변수에 넣을 때 사용되는 페이지와 동일한 양입니다.
느린 계획의 경우 이러한 페이지 할당 수는 수백만입니다. dm_db_task_space_usage
쿼리가 실행되는 동안 폴링 은 tempdb
한 번에 1,800 ~ 3,000 페이지 사이의 페이지를 지속적으로 할당하고 할당을 해제하는 것으로 보입니다 .
WHERE
절을 XQuery 표현식으로 이동할 수 있습니다 . 로직을 빨리 제거하기 위해 제거 할 필요는 없습니다TargetData.nodes ('RingBufferTarget[1]/event[@name = "xml_deadlock_report"]')
. 즉, 나는 당신이 제기 한 질문에 대답하기에 충분히 XML 내부를 모른다.