Загрузка процессора базой данных?
-
09-06-2019 - |
Вопрос
Можно ли получить разбивку по загрузке процессора по базе данных?
Я в идеале ищу интерфейс типа диспетчера задач для SQL server, но вместо того, чтобы смотреть на загрузку процессора каждым PID (например taskmgr
) или каждый SPID (например spwho2k5
), я хочу просмотреть общую загрузку процессора каждой базы данных.Предположим, что имеется один экземпляр SQL.
Я понимаю, что можно было бы написать инструменты для сбора этих данных и составления отчетов по ним, но мне интересно, есть ли какой-нибудь инструмент, который позволяет мне в режиме реального времени видеть, какие базы данных вносят наибольший вклад в sqlservr.exe
Загрузка процессора.
Решение
Вроде того.Ознакомьтесь с этим запросом:
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 корпорация Майкрософт представила функции управления производительностью и приложениями, которые позволят нам упаковать единую базу данных в распространяемый и развертываемый пакет DAC, и они обещают упростить управление производительностью отдельных баз данных и их приложений.Однако это все равно не дает того, что вы ищете.
Для получения дополнительной информации ознакомьтесь с Репозиторий T-SQL в Toad World's SQL Server wiki (ранее в SQLServerPedia).
Обновлено 1/29, чтобы включить общие цифры, а не только средние.
Другие советы
SQL Server (начиная с 2000 года) установит счетчики производительности (доступные для просмотра с помощью Performance Monitor или Perfmon).
Одной из категорий счетчиков (при установке SQL Server 2005 является:) - SQLServer: базы данных
С одним экземпляром для каждой базы данных.Доступные счетчики, однако, не предоставляют счетчик загрузки процессора в процентах или что-то подобное, хотя есть несколько счетчиков скорости, которые вы могли бы использовать, чтобы получить хорошую оценку процессора.Примером может быть, если у вас есть 2 базы данных, и измеряемая скорость составляет 20 транзакций в секунду в базе данных A и 80 транзакций в секунду в базе данных B - тогда вы бы знали, что A обеспечивает примерно 20% от общего объема процессора, а B - остальные 80%.
Здесь есть некоторые недостатки, поскольку предполагается, что вся выполняемая работа привязана к процессору, чего, конечно, с базами данных нет.Но я верю, что это было бы началом.
Вот запрос, который покажет фактическую базу данных, вызывающую высокую нагрузку.Он полагается на кэш запросов, который может часто очищаться в сценариях с низким объемом памяти (что делает запрос менее полезным).
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
Я думаю, что ответ на ваш вопрос - нет.
Проблема в том, что одно действие на компьютере может вызвать нагрузку на несколько баз данных.Если у меня есть процесс, который считывает данные из базы данных конфигурации, регистрируется в базе данных ведения журнала и перемещает транзакции в различные базы данных и из них в зависимости от типа, как мне разделить загрузку процессора?
Вы могли бы разделить загрузку процессора на загрузку транзакций, но это опять же грубый показатель, который может ввести вас в заблуждение.Например, как бы вы разделили доставку журналов транзакций из одной базы данных в другую?Загружается ли процессор при чтении или записи?
Вам лучше обратить внимание на скорость транзакций для компьютера и нагрузку на процессор, которую это вызывает.Вы также могли бы профилировать хранимые процедуры и посмотреть, не отнимает ли какая-либо из них чрезмерно много времени;однако это не даст вам желаемого ответа.
Имея в виду все сказанное выше.
Начиная с SQL Server 2012 (может быть 2008 ?) , есть столбец идентификатор базы данных в системные.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;
Взгляните на SQL - часовой.Он делает все, что вам нужно, и даже больше.
С уважением, Ливен
Вы смотрели на SQL profiler?
Возьмите стандартный шаблон "T-SQL" или "Хранимая процедура", настройте поля для группировки по идентификатору базы данных (я думаю, вы должны использовать номер, вы не получаете имя базы данных, но это легко узнать, используя exec sp_databases для получения списка)
Запустите это на некоторое время, и вы получите общее количество процессоров / Ввод-вывод с диска / Ожидание и т.д.Это может дать вам долю процессора, используемого каждой базой данных.
Если вы одновременно отслеживаете счетчик PerfMon (регистрируете данные в базе данных SQL) и делаете то же самое для SQL Profiler (регистрируете в базе данных), вы мочь умейте соотносить эти два явления вместе.
Тем не менее, это должно дать вам достаточное представление о том, на какую базу данных стоит обратить более пристальное внимание.Затем проделайте то же самое еще раз только с этим идентификатором базы данных и найдите самые дорогие SQL / хранимые процедуры.
пожалуйста, проверьте этот запрос:
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