Wykonanie zapytania stąd, aby wyciągnąć zdarzenia impasu z domyślnej sesji zdarzeń rozszerzonych
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';
wykonanie na moim komputerze zajmuje około 20 minut. Zgłoszone statystyki to
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.
Jeśli usunę WHERE
klauzulę, wypełnia się ona w mniej niż sekundę, zwracając 3782 wiersze.
Podobnie, jeśli dodam OPTION (MAXDOP 1)
do pierwotnego zapytania, które również przyspiesza, statystyki pokazują teraz znacznie mniej odczytów 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.
Więc moje pytanie brzmi
Czy ktoś może wyjaśnić, co się dzieje? Dlaczego pierwotny plan jest tak katastrofalnie gorszy i czy istnieje jakiś niezawodny sposób na uniknięcie problemu?
Dodanie:
Przekonałem się również, że zmiana zapytania do INNER HASH JOIN
pewnego stopnia poprawia (ale nadal zajmuje> 3 minuty), ponieważ wyniki DMV są tak małe, że wątpię, czy sam typ łączenia jest odpowiedzialny i zakładam, że coś innego musiało się zmienić. Statystyki dla tego
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.
Po napełnieniu bufor pierścieniowy wydłużone zdarzenia ( DATALENGTH
z XML
było 4,880,045 bajtów i zawierał 1,448 zdarzeń.) I prób ściętego wersji oryginalnego zapytania z i bez MAXDOP
śladu.
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
Dał następujące wyniki
+-------------------------------------+------+----------+
| | 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 |
+-------------------------------------+------+----------+
Istnieje wyraźna różnica w alokacjach tempdb w tym, że szybciej pokazuje 616
strony przydzielone i cofnięte. Jest to ta sama liczba stron, która jest używana, gdy XML jest również wstawiany do zmiennej.
W przypadku powolnego planu liczba przydziałów stron jest wyrażona w milionach. Sondowanie dm_db_task_space_usage
podczas działania zapytania pokazuje, że wydaje się ono stale przydzielać i zwalniać strony tempdb
z dowolnym miejscem między 1800 a 3000 stron jednocześnie.
WHERE
klauzulę do wyrażenia XQuery; logika nie muszą być usunięte na to, aby go szybko:TargetData.nodes ('RingBufferTarget[1]/event[@name = "xml_deadlock_report"]')
. To powiedziawszy, nie znam wewnętrznych elementów XML wystarczająco dobrze, aby odpowiedzieć na postawione pytanie.