Виконання запиту звідси, щоб витягнути події з глухого кута поза сеансом розширених подій за замовчуванням
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
пункт, він завершиться менш ніж за секунду, повертаючи 3782 рядки.
Аналогічно, якщо я додаю 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 настільки малі, я сумніваюся, що сам тип 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 |
+-------------------------------------+------+----------+
Існує чітка відмінність у розміщенні tempdb у більш швидкому 616
розміщенні та розміщенні сторінок, що показують . Це стільки ж сторінок, що використовуються, коли XML також вводиться в змінну.
Для повільного плану, кількість цих сторінок розподіляється на мільйони. Опитування dm_db_task_space_usage
під час запуску запиту показує, що, здається, він постійно розподіляє та tempdb
розміщує сторінки на будь-яких місцях від 1800 до 3000 сторінок, виділених у будь-який час.
WHERE
пункт у вираз XQuery; логіка не повинна бути видалена для того , щоб йти швидко:TargetData.nodes ('RingBufferTarget[1]/event[@name = "xml_deadlock_report"]')
. Це означає, що я не знаю внутрішніх даних XML досить добре, щоб відповісти на поставлене вами питання.