Выполнение запроса отсюда, чтобы извлечь тупиковые события из сеанса расширенных событий по умолчанию
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, чтобы ответить на поставленный вами вопрос.