ดำเนินการค้นหาจากที่นี่เพื่อดึงเหตุการณ์ deadlock ออกจากเซสชันเพิ่มเติมของเหตุการณ์ที่ขยายเริ่มต้น
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 แถว
ในทำนองเดียวกันถ้าฉันเพิ่มลง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
ปรับปรุงบางสิ่งบางอย่าง (แต่ยังคงใช้เวลา> 3 นาที) เนื่องจากผลลัพธ์ DMV มีขนาดเล็กมากฉันสงสัยว่าตัวเองประเภทเข้าร่วมเป็นผู้รับผิดชอบแต่ทว่าและต้องมีการเปลี่ยนแปลงอย่างอื่น สถิติสำหรับสิ่งนั้น
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 ไบต์และมีกิจกรรม 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
ในขณะที่เรียกใช้แบบสอบถามแสดงว่าดูเหมือนว่าจะมีการจัดสรรและยกเลิกการจัดสรรหน้าอย่างต่อเนื่องในtempdb
ทุก ๆ ที่ระหว่าง 1,800 ถึง 3,000 หน้าในแต่ละครั้ง
WHERE
ประโยคไปที่นิพจน์ XQuery; ตรรกะไม่จำเป็นต้องถูกลบออกเพื่อให้มันไปอย่างรวดเร็ว:TargetData.nodes ('RingBufferTarget[1]/event[@name = "xml_deadlock_report"]')
. ที่กล่าวว่าฉันไม่ทราบว่า XML internals ดีพอที่จะตอบคำถามที่คุณโพสต์