是否有可能获得 CPU 利用率的详细信息 通过数据库?

我理想地寻找 SQL Server 的任务管理器类型接口,而不是查看每个 PID 的 CPU 利用率(例如 taskmgr)或每个 SPID(例如 spwho2k5),我想查看每个数据库的CPU总利用率。假设有一个 SQL 实例。

我意识到可以编写工具来收集这些数据并报告它,但我想知道是否有任何工具可以让我实时查看哪些数据库对数据贡献最大 sqlservr.exe CPU负载。

有帮助吗?

解决方案

有点。检查这个查询:

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

这将为您提供计划缓存中的查询,按照它们使用了多少 CPU 的顺序排列。您可以定期运行此命令(就像在 SQL 代理作业中一样),并将结果插入到表中,以确保数据在重新启动后仍然存在。

当您阅读结果时,您可能会意识到为什么我们不能将该数据直接关联回单个数据库。首先,单个查询还可以通过执行以下技巧来隐藏其真正的数据库父级:

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

该查询将在 MSDB 中执行,但会从 AdventureWorks 轮询结果。我们应该在哪里分配CPU消耗?

当你出现以下情况时,情况会变得更糟:

  • 多个数据库之间的连接
  • 在多个数据库中运行事务,并且锁定工作跨越多个数据库
  • 在 MSDB 中运行在 MSDB 中“工作”的 SQL 代理作业,但备份单个数据库

它会一直持续下去。这就是为什么在查询级别而不是数据库级别进行性能调整更有意义。

在 SQL Server 2008R2 中,Microsoft 引入了性能管理和应用程序管理功能,使我们能够将单个数据库打包在可分发和可部署的 DAC 包中,并且它们有望使管理单个数据库及其应用程序的性能变得更加容易。但它仍然没有达到您想要的效果。

有关更多内容,请查看 Toad World 的 SQL Server wiki 中的 T-SQL 存储库(以前位于 SQLServerPedia).

于 1/29 更新,包含总数而不仅仅是平均值。

其他提示

SQL Server(从2000开始)将安装性能计数器(可从性能监视器或Perfmon查看)。

计数类别之一(来自SQL Server 2005 Install是:) -SQLServer:数据库

每个数据库都有一个实例。然而,可用的计数器不提供 CPU 利用率计数器或类似的东西,尽管有一些速率计数器,您可以使用它们来获得 CPU 的良好估计。示例是,如果您有 2 个数据库,并且测得的数据库 A 上的速率为 20 个事务/秒,数据库 B 上的速率为 80 个事务/秒 --- 那么您就会知道 A 大约占总 CPU 的 20%,并且B贡献了其他80%。

这里存在一些缺陷,因为假设所有正在完成的工作都是 CPU 限制的,当然数据库则不然。但我相信这将是一个开始。

这是一个查询,将显示导致高负载的实际数据库。它依赖于查询缓存,在内存不足的情况下,查询缓存可能会被频繁刷新(使得查询不太有用)。

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

我认为你的问题的答案是否定的。

问题是一台机器上的一项活动可能会导致多个数据库负载。如果我有一个进程正在从配置数据库读取数据、记录到日志数据库以及根据类型将事务移入和移出各种数据库,那么如何对 CPU 使用情况进行分区?

您可以将 CPU 利用率除以事务负载,但这又是一个可能会误导您的粗略指标。例如,您如何将事务日志传送从一个数据库划分到另一个数据库?CPU负载是读还是写?

您最好查看机器的事务率及其导致的 CPU 负载。您还可以分析存储过程并查看其中是否有任何一个花费了过多的时间;然而,这不会给你你想要的答案。

考虑到上述所有内容。
从 SQL Server 2012(可能是 2008?)开始,有列 数据库IDsys.dm_exec_sessions.
它使我们可以轻松计算每个数据库的 cpu 当前已连接 会议。如果会话已断开连接,则其结果将消失。

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哨兵. 。它可以满足您的所有需求,甚至更多。

问候,lieven

你看过 SQL 分析器吗?

采用标准的“T-SQL”或“存储过程”模板,调整字段以按数据库 ID 分组(我认为您必须使用数字,您不会获得数据库名称,但使用 exec sp_databases 很容易找到获取列表)

运行一段时间,您将获得总 CPU 计数/磁盘 IO/等待等。这可以为您提供每个数据库使用的 CPU 比例。

如果您同时监视 PerfMon 计数器(将数据记录到 SQL 数据库),并对 SQL Profiler 执行相同的操作(记录到数据库),则您可以 可能 能够将两者关联在一起。

即便如此,它也应该为您提供足够的线索,让您知道哪个数据库值得更详细地研究。然后,仅使用该数据库 ID 再次执行相同操作,并查找最昂贵的 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
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top