2008-08-26 5 views
29

Возможно ли получить разбивку использования ЦП по базе данных?Загрузка процессора по базе данных?

Я идеально ищу интерфейс интерфейса диспетчера задач для SQL-сервера, но вместо того, чтобы смотреть на использование ЦП каждого ПИД-кода (например, taskmgr) или каждый SPID (например, spwho2k5), я хочу просмотреть общее использование ЦП каждой базы данных. Предположим, что один экземпляр SQL.

Я понимаю, что инструменты могут быть записаны для сбора этих данных и отчета об этом, но мне интересно, есть ли какой-либо инструмент, который позволяет мне видеть живое представление о том, какие базы данных вносят наибольший вклад в нагрузку процессора sqlservr.exe.

ответ

81

Сорт. Проверить этот запрос из:

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 

Это поможет вам запросы в кэше плана в порядке, сколько процессора они использовали. Вы можете запускать это периодически, как в задании агента SQL, и вставлять результаты в таблицу, чтобы убедиться, что данные остаются за перезагрузкой.

Когда вы читаете результаты, вы, вероятно, поймете, почему мы не можем соотнести эти данные непосредственно с отдельной базой данных. Во-первых, один запрос может также скрыть свой истинный родительский базы данных, делая трюки, как это:

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

Запрос будет выполнен в MSDB, но было бы результаты опроса из AdventureWorks. Где мы должны назначать потребление ЦП?

Это становится хуже, когда вы:

  • Регистрация между несколькими базами данных
  • запустить транзакций в нескольких базах данных, а также усилия запирающей охватывает несколько баз данных
  • заданий Выполнить SQL агента в MSDB, что «работа» в MSDB, но резервное копирование отдельных баз данных

Это продолжается и продолжается. Поэтому имеет смысл настраивать производительность на уровне запросов, а не на уровне базы данных.

В SQL Server 2008R2 Microsoft представила функции управления производительностью и управления приложениями, которые позволят нам упаковать одну базу данных в распространяемом и развертываемом пакете DAC, и они являются многообещающими функциями, чтобы упростить управление производительностью отдельных баз данных и их применения. Тем не менее, он все еще не делает то, что вы ищете.

Для получения дополнительной информации посетите T-SQL repository at Toad World's SQL Server wiki (formerly at SQLServerPedia).

Обновлено на 1/29, чтобы включить общее число вместо средних.

+1

Простите мое невежество, но каковы единицы AvgCPU и AvgDuration? – Portman 2009-01-28 23:56:22

15

SQL Server (начиная с 2000 года) установит счетчики производительности (можно просматривать из Performance Monitor или Perfmon).

Один из встречных категорий (от SQL Server 2005 установить это :) - SQLServer: Базы данных

С одного экземпляра для каждой базы данных. Однако доступные счетчики не обеспечивают счетчик использования% CPU или что-то подобное, хотя есть некоторые счетчики скорости, которые можно использовать для получения хорошей оценки CPU. Например, если у вас есть 2 базы данных, а измеренная скорость составляет 20 транзакций/с в базе данных A и 80 транзакций/сек в базе данных B - тогда вы бы знали, что A составляет примерно 20% от общего ЦП и B способствует другим 80%.

Здесь есть некоторые недостатки, так как предполагается, что все выполняемые работы связаны с ЦП, что, конечно же, с базами данных - это не так. Но это было бы началом, на которое я верю.

1

Я думаю, что ответ на ваш вопрос - нет.

Проблема в том, что одно действие на машине может вызвать нагрузку на несколько баз данных. Если у меня есть процесс, который читается из конфигурационного БД, регистрируется в БД регистрации и перемещает транзакции в и из разных БД на основе типа, как мне разделить использование ЦП?

Вы можете разделить загрузку процессора на транзакционную нагрузку, но это опять же приблизительная метрика, которая может ввести вас в заблуждение. Например, как бы вы разделили транзакционный журнал с одного БД на другой? Является ли загрузка ЦП при чтении или записи?

Вам лучше смотреть на скорость транзакции для машины и загрузку процессора. Вы также можете просмотреть хранимые процедуры и посмотреть, не требуется ли какое-либо из них чрезмерное количество времени; однако, это не даст вам ответ, который вы хотите.

0

Посмотрите на SQL Sentry. Он делает все, что вам нужно, и многое другое.

С уважением, Ливен

0

Вы смотрели на SQL Profiler?

Возьмите стандартный шаблон «T-SQL» или «Сохраненная процедура», настройте поля для группировки по идентификатору базы данных (я думаю, вы должны использовать этот номер, вы не получите имя базы данных, но его легко найти используя exec sp_databases для получения списка)

Запустите это некоторое время, и вы получите общее количество CPU/Disk IO/Wait и т. д. Это может дать вам долю процессора, используемого каждой базой данных.

Если следить за счетчиком PerfMon одновременно (регистрировать данные в базу данных SQL), и сделать то же самое для SQL Profiler (вход в базу данных), то может быть в состоянии соотнести их друг с другом.

Несмотря на это, он должен дать вам достаточно информации о том, какую БД стоит рассмотреть более подробно. Затем повторите то же самое с помощью только этого идентификатора базы данных и найдите самые дорогие SQL/хранимые процедуры.

6

Вот запрос, который покажет фактическую базу данных, вызывающую высокую нагрузку. Он полагается на кеш запросов, который может часто сбрасываться в сценариях с низкой памятью (что делает запрос менее полезным).

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

пожалуйста, проверьте этот запрос:

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

С все сказанное выше в виду.
Начиная с SQL Server 2012 (может быть, 2008?), есть столбец database_id in sys.dm_exec_sessions.
Это дает нам простой расчет процессора для каждой базы данных для в настоящее время подключен сеансов. Если сеанс отключен, результаты его исчезли.

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; 
Смежные вопросы