Chociaż, podobnie jak @Thomas, całkowicie zgadzam się z @Aaron w komentarzach dotyczących pytania, czy obawy dotyczące „wykorzystania procesora na bazę danych” są dokładne lub przydatne, mogę przynajmniej odpowiedzieć na pytanie, dlaczego te dwa zapytania są tak różne. A powód, dla którego się różnią, wskaże, który z nich jest dokładniejszy, chociaż ten wyższy poziom dokładności jest nadal związany z tym, który jest szczególnie niedokładny, a zatem nadal nie jest naprawdę dokładny ;-).
Pierwsze zapytanie używa sys.dm_exec_query_stats, aby uzyskać informacje o procesorze (tj total_worker_time
.). Jeśli przejdziesz na linkowaną stronę, która jest dokumentacją MSDN dla tego DMV, zobaczysz krótkie, 3-zdaniowe wprowadzenie, a 2 z tych zdań dają nam większość tego, czego potrzebujemy, aby zrozumieć kontekst tych informacji („jak wiarygodny” i „jak to się ma do sys.sysprocesses
”). Te dwa zdania to:
Zwraca zagregowane statystyki wydajności dla buforowanych planów zapytań w SQL Server. ... Gdy plan zostanie usunięty z pamięci podręcznej, odpowiednie wiersze zostaną wyeliminowane z tego widoku
Pierwsze zdanie, „Zwraca zagregowane statystyki wydajności”, mówi nam, że informacje w tym DMV (podobnie jak kilka innych) są kumulatywne i nie są specyficzne tylko dla aktualnie uruchomionych zapytań. Wskazuje na to również pole w tym DMV, które nie jest częścią zapytania w pytaniu execution_count
, co ponownie pokazuje, że są to dane skumulowane. Przydatne jest, aby te dane były kumulatywne, ponieważ można uzyskać średnie itp., Dzieląc niektóre metryki przez execution_count
.
Drugie zdanie: „plany usuwane z pamięci podręcznej są również usuwane z tego DMV”, wskazuje, że wcale nie jest to kompletny obraz, szczególnie jeśli serwer ma już dość pełną pamięć podręczną planu i jest obciążony, a zatem plany wygasają nieco częściej. Ponadto większość DMV jest resetowanych po zresetowaniu serwera, więc nie są prawdziwą historią, nawet jeśli te wiersze nie zostały usunięte po wygaśnięciu planów.
Porównajmy teraz powyższe sys.sysprocesses
. Ten widok systemu pokazuje tylko to, co jest aktualnie uruchomione, podobnie jak kombinacja sys.dm_exec_connections , sys.dm_exec_sessions i sys.dm_exec_requests (co podano na stronie z linkami dla sys.dm_exec_sessions
). Jest to zupełnie inny widok serwera w porównaniu do sys.dm_exec_query_stats
DMV, który przechowuje dane nawet po zakończeniu procesu. Czyli w związku z „czy wyniki drugiego zapytania są nieprawidłowe?” pytanie, nie są w błędzie, po prostu odnoszą się do innego aspektu (tj. ramy czasowe) statystyk wydajności.
Tak więc zapytanie używa sys.sysprocesses
tylko „teraz”. Za pomocą zapytania sys.dm_exec_query_stats
sprawdza się głównie (być może) to, co się wydarzyło od ostatniego restartu usługi SQL Server (lub oczywiście ponownego uruchomienia systemu). W przypadku ogólnej analizy wydajności wydaje się, że sys.dm_exec_query_stats
jest o wiele lepsza, ale znowu pozostawia przydatne informacje przez cały czas. W obu przypadkach należy również wziąć pod uwagę uwagi przedstawione przez @Aaron w komentarzach do pytania (ponieważ usunięto) dotyczące dokładności wartości „id_bazy_danych” w pierwszej kolejności (tzn. Odzwierciedla ona tylko aktywną bazę danych, która zainicjowała kod , niekoniecznie tam, gdzie występuje „problem”).
Ale, jeśli wystarczy / chcą zorientować się, co dzieje się teraz we wszystkich bazach danych, być może dlatego, że rzeczy spowalnia teraz, jesteś lepiej wyłączyć za pomocą kombinacji sys.dm_exec_connections
, sys.dm_exec_sessions
i sys.dm_exec_requests
(a nie przestarzałe sys.sysprocesses
). Pamiętaj tylko, że szukasz zapytań , a nie baz danych , ponieważ zapytania mogą łączyć się w wielu bazach danych, włączając UDF z jednej lub więcej baz danych itp.
EDYCJA:
Jeśli ogólną obawą jest zmniejszenie liczby konsumentów o wysokim procesorze, poszukaj zapytań, które zajmują najwięcej procesora, ponieważ bazy danych tak naprawdę nie zajmują procesora (wyszukiwanie według bazy danych może działać w firmie hostingowej, w której każda baza danych jest izolowana i należąca do innego klienta).
Poniższe zapytanie pomoże zidentyfikować zapytania o wysokim średnim zużyciu procesora. Kondensuje dane w DM_st query_stats, ponieważ te rekordy mogą pokazywać to samo zapytanie (tak, ten sam podzbiór partii zapytania) wiele razy, każdy z innym planem wykonania.
;WITH cte AS
(
SELECT stat.[sql_handle],
stat.statement_start_offset,
stat.statement_end_offset,
COUNT(*) AS [NumExecutionPlans],
SUM(stat.execution_count) AS [TotalExecutions],
((SUM(stat.total_logical_reads) * 1.0) / SUM(stat.execution_count)) AS [AvgLogicalReads],
((SUM(stat.total_worker_time) * 1.0) / SUM(stat.execution_count)) AS [AvgCPU]
FROM sys.dm_exec_query_stats stat
GROUP BY stat.[sql_handle], stat.statement_start_offset, stat.statement_end_offset
)
SELECT CONVERT(DECIMAL(15, 5), cte.AvgCPU) AS [AvgCPU],
CONVERT(DECIMAL(15, 5), cte.AvgLogicalReads) AS [AvgLogicalReads],
cte.NumExecutionPlans,
cte.TotalExecutions,
DB_NAME(txt.[dbid]) AS [DatabaseName],
OBJECT_NAME(txt.objectid, txt.[dbid]) AS [ObjectName],
SUBSTRING(txt.[text], (cte.statement_start_offset / 2) + 1,
(
(CASE cte.statement_end_offset
WHEN -1 THEN DATALENGTH(txt.[text])
ELSE cte.statement_end_offset
END - cte.statement_start_offset) / 2
) + 1
)
FROM cte
CROSS APPLY sys.dm_exec_sql_text(cte.[sql_handle]) txt
ORDER BY cte.AvgCPU DESC;
AvgCPU
w milisekundach?