2008-08-26 40 views
29

Czy można uzyskać podział wykorzystania procesora według bazy danych?Wykorzystanie procesora przez bazę danych?

mam idealnie szuka interfejsu typu Task Manager dla serwera SQL, ale zamiast patrzenia na wykorzystanie procesora każdego PID (jak taskmgr) lub każdy SPID (jak spwho2k5), chcę, aby wyświetlić całkowitą wykorzystanie procesora każdej bazy danych. Załóżmy pojedynczą instancję SQL.

Zdaję sobie sprawę, że można napisać narzędzia do zbierania tych danych i raportowania, ale zastanawiam się, czy istnieje jakieś narzędzie, które pozwala mi zobaczyć widok na żywo, z którego bazy danych wnoszą największy wkład do obciążenia procesora sqlservr.exe.

Odpowiedz

81

Sortuj. Sprawdź to zapytanie:

SELECT total_worker_time/execution_count AS AvgCPU 
, total_worker_time AS TotalCPU 
, total_elapsed_time/execution_count AS AvgDuration 
, total_elapsed_time AS TotalDuration 
, (total_logical_reads+total_physical_reads)/execution_count AS AvgReads 
, (total_logical_reads+total_physical_reads) AS TotalReads 
, execution_count 
, SUBSTRING(st.TEXT, (qs.statement_start_offset/2)+1 
, ((CASE qs.statement_end_offset WHEN -1 THEN datalength(st.TEXT) 
ELSE qs.statement_end_offset 
END - qs.statement_start_offset)/2) + 1) AS txt 
, query_plan 
FROM sys.dm_exec_query_stats AS qs 
cross apply sys.dm_exec_sql_text(qs.sql_handle) AS st 
cross apply sys.dm_exec_query_plan (qs.plan_handle) AS qp 
ORDER BY 1 DESC 

Spowoduje to wyświetlenie zapytań w pamięci podręcznej planu w kolejności zużytego procesora. Możesz uruchamiać to okresowo, jak w zadaniu agenta SQL, i wstawić wyniki do tabeli, aby upewnić się, że dane będą się utrzymywać po ponownym uruchomieniu.

Po przeczytaniu wyników prawdopodobnie uświadomisz sobie, dlaczego nie możemy skorelować tych danych bezpośrednio z indywidualną bazą danych. Po pierwsze, jedno zapytanie można również ukryć swój prawdziwy bazy rodzica wykonując sztuczki tak:

USE msdb 
DECLARE @StringToExecute VARCHAR(1000) 
SET @StringToExecute = 'SELECT * FROM AdventureWorks.dbo.ErrorLog' 
EXEC @StringToExecute 

Kwerenda będzie wykonywany w MSDB, ale to wyniki ankiety z AdventureWorks. Gdzie powinniśmy przypisać zużycie procesora?

Jest jeszcze gorzej, gdy:

  • Dołącz pomiędzy wieloma bazami danych
  • uruchomienia transakcji w wielu bazach danych i wysiłku blokujący obejmuje wiele baz
  • Run SQL agenta zadania w msdb, że „praca” w MSDB, ale kopii zapasowych poszczególnych baz danych

To trwa. Dlatego ma sens, aby dostroić wydajność na poziomie zapytania zamiast na poziomie bazy danych.

W SQL Server 2008R2 Microsoft wprowadził funkcje zarządzania wydajnością i zarządzania aplikacjami, które pozwolą nam spakować pojedynczą bazę danych w dystrybuowalnym i dającym się wdrożyć pakiecie DAC, i są obiecującymi funkcjami, które ułatwiają zarządzanie wydajnością poszczególnych baz danych i ich aplikacje. Wciąż jednak nie robi tego, czego szukasz.

Aby uzyskać więcej takich informacji, sprawdź numer T-SQL repository at Toad World's SQL Server wiki (formerly at SQLServerPedia).

Zaktualizowano na 1/29, aby uwzględnić całkowitą liczbę zamiast tylko średnich.

+1

Wybacz moją niewiedzę, ale jakie są jednostki AvgCPU i AvgDuration? – Portman

+1

Milisekundy dla obu - milisekund czasu procesora i milisekund trwania. Mogą być różne, ponieważ zapytania mogą czekać na IO, blokady, klientów itp. Zmodyfikuję zapytanie, aby pobrać również sumy. (Chciałem powiedzieć, funty, ale nie mogłem zachować wirtualnej prostej twarzy.) –

15

Serwer SQL (począwszy od 2000) zainstaluje liczniki wydajności (widoczne z Monitora wydajności lub Perfmon).

Jedną z kategorii Licznik (z SQL Server 2005 instalują jest :) - SQLServer: Databases

Z jednej instancji dla każdej bazy danych. Dostępne liczniki nie zapewniają jednak licznika wykorzystania CPU% lub czegoś podobnego, chociaż istnieją pewne liczniki szybkości, które można wykorzystać do uzyskania dobrego oszacowania procesora. Przykładem może być, jeśli masz dwie bazy danych, a zmierzona szybkość wynosi 20 transakcji/s dla bazy danych A i 80 trans/s dla bazy danych B --- to wtedy wiesz, że A ma około 20% całkowitej mocy procesora, i B przyczynia się do innych 80%.

Istnieje kilka błędów, ponieważ zakładamy, że cała praca wykonywana jest z CPU, co oczywiście z bazami danych nie jest. Ale sądzę, że to byłby początek.

1

Myślę, że odpowiedź na twoje pytanie brzmi: nie.

Problem polega na tym, że jedno działanie na komputerze może spowodować ładowanie wielu baz danych. Jeśli mam proces, który czyta z pliku konfiguracyjnego DB, logując się do bazy danych rejestrowania i przenosząc transakcje do i z różnych baz danych na podstawie typu, w jaki sposób mogę podzielić użycie procesora?

Można podzielić wykorzystanie procesora przez obciążenie transakcją, ale jest to ponownie przybliżona metryka, która może wprowadzić użytkownika w błąd. Jak na przykład podzielisz wysyłkę dzienników transakcji z jednego DB na inny? Czy obciążenie procesora jest podczas odczytu lub zapisu?

Lepiej spróbuj spojrzeć na stawkę transakcji dla komputera i obciążenia procesora, które powoduje. Można również profilować przechowywane procedury i sprawdzać, czy któreś z nich zajmuje nadmierną ilość czasu; jednak nie dostaniesz odpowiedzi, której potrzebujesz.

0

Spójrz na SQL Sentry. Robi wszystko, czego potrzebujesz i więcej.

Pozdrowienia, Lieven

0

Pan spojrzał na SQL Profiler?

Weź standardowy szablon "T-SQL" lub "Zapisana procedura", dostosuj pola do grupy według identyfikatora bazy danych (Myślę, że musisz użyć numeru, nie masz nazwy bazy danych, ale łatwo jest znaleźć out przy użyciu exec sp_databases, aby uzyskać listę)

Uruchom to przez chwilę, a otrzymasz całkowitą liczbę procesorów/Disk IO/Wait itp. To może dać ci procent CPU użytego przez każdą bazę danych.

Jeśli monitorujesz jednocześnie licznik PerfMon (zapisuj dane w bazie danych SQL) i zrób to samo dla programu SQL Profiler (loguj do bazy danych), możesz być w stanie skorelować te dwa elementy razem.

Mimo to powinien dać ci wystarczająco dużo informacji na temat tego, na który DB warto zwrócić uwagę. Następnie wykonaj to samo ponownie, używając tylko tego identyfikatora bazy danych i wyszukaj najdroższe SQL/Procedury składowane.

6

Oto zapytanie, które wyświetli rzeczywistą bazę danych powodującą duże obciążenie. Opiera się na pamięci podręcznej zapytań, która może być często przepłukiwana w scenariuszach o niskiej pamięci (dzięki czemu zapytanie jest mniej użyteczne).

select dbs.name, cacheobjtype, total_cpu_time, total_execution_count from 
    (select top 10 
     sum(qs.total_worker_time) as total_cpu_time, 
     sum(qs.execution_count) as total_execution_count, 
     count(*) as number_of_statements, 
     qs.plan_handle 
    from 
     sys.dm_exec_query_stats qs 
    group by qs.plan_handle 
    order by sum(qs.total_worker_time) desc 
    ) a 
inner join 
(SELECT plan_handle, pvt.dbid, cacheobjtype 
FROM (
    SELECT plan_handle, epa.attribute, epa.value, cacheobjtype 
    FROM sys.dm_exec_cached_plans 
     OUTER APPLY sys.dm_exec_plan_attributes(plan_handle) AS epa 
    /* WHERE cacheobjtype = 'Compiled Plan' AND objtype = 'adhoc' */) AS ecpa 
PIVOT (MAX(ecpa.value) FOR ecpa.attribute IN ("dbid", "sql_handle")) AS pvt 
) b on a.plan_handle = b.plan_handle 
inner join sys.databases dbs on dbid = dbs.database_id 
0

proszę sprawdzić to zapytanie:

SELECT 
    DB_NAME(st.dbid) AS DatabaseName 
    ,OBJECT_SCHEMA_NAME(st.objectid,dbid) AS SchemaName 
    ,cp.objtype AS ObjectType 
    ,OBJECT_NAME(st.objectid,dbid) AS Objects 
    ,MAX(cp.usecounts)AS Total_Execution_count 
    ,SUM(qs.total_worker_time) AS Total_CPU_Time 
    ,SUM(qs.total_worker_time)/(max(cp.usecounts) * 1.0) AS Avg_CPU_Time 
FROM sys.dm_exec_cached_plans cp 
INNER JOIN sys.dm_exec_query_stats qs 
    ON cp.plan_handle = qs.plan_handle 
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st 
WHERE DB_NAME(st.dbid) IS NOT NULL 
GROUP BY DB_NAME(st.dbid),OBJECT_SCHEMA_NAME(objectid,st.dbid),cp.objtype,OBJECT_NAME(objectid,st.dbid) 
ORDER BY sum(qs.total_worker_time) desc 
1

Z wszystkich wyżej powiedziano w umyśle.
Począwszy od SQL Server 2012 (może być 2008?) znajduje się kolumna database_id w sys.dm_exec_sessions.
Daje nam to łatwe obliczenia procesora dla każdej bazy danych dla aktualnie połączonych sesji. Jeśli sesja się rozłączyła, jej wyniki zniknęły.

select session_id, cpu_time, program_name, login_name, database_id 
    from sys.dm_exec_sessions 
where session_id > 50; 

select sum(cpu_time)/1000 as cpu_seconds, database_id 
from sys.dm_exec_sessions 
group by database_id 
order by cpu_seconds desc; 
Powiązane problemy