代码之家  ›  专栏  ›  技术社区  ›  Portman

按数据库划分的CPU利用率?

  •  30
  • Portman  · 技术社区  · 16 年前

    有可能得到CPU利用率的明细吗 通过数据库 ?

    理想情况下,我会为SQL Server寻找一个任务管理器类型的接口,但不会考虑每个PID的CPU利用率(如 taskmgr )或每个SPID(如 spwho2k5 ,我想查看每个数据库的总CPU利用率。假设一个SQL实例。

    我知道可以编写工具来收集这些数据并对其进行报告,但是我想知道是否有任何工具可以让我看到哪些数据库对 sqlservr.exe CPU负载。

    8 回复  |  直到 7 年前
        1
  •  81
  •   Brent Ozar    11 年前

    某种程度上。签出此查询:

    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包中,而且这些功能有望使管理单个数据库及其应用程序的性能变得更容易。不过,它仍然不能满足你的需求。

    更多信息,请查看 T-SQL repository at Toad World's SQL Server wiki (formerly at SQLServerPedia) .

    在1/29更新,包括总数字,而不仅仅是平均数。

        2
  •  15
  •   Adam    16 年前

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

    计数器类别之一(来自SQL Server 2005安装为:) -SQLServer:数据库

    每个数据库有一个实例。但是,可用的计数器不提供CPU%利用率计数器或类似的计数器,尽管有一些速率计数器,您可以使用它们来获得对CPU的良好估计。例如,如果您有两个数据库,并且测量的速率为数据库A上的20个事务/秒和数据库B上的80个事务/秒,那么您将知道A大约占总CPU的20%,而B则占其他80%。

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

        3
  •  6
  •   friism    12 年前

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

    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
    
        4
  •  1
  •   Ry Jones    15 年前

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

    问题是一台机器上的一个活动可能会导致多个数据库上的负载。如果我有一个进程正在从一个配置数据库读取数据,记录到一个日志数据库,并根据类型将事务移入和移出不同的数据库,我该如何划分CPU使用率?

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

    你最好看看一台机器的事务速率和它导致的CPU负载。您还可以对存储过程进行概要分析,看看它们中是否有任何一个占用了过多的时间;但是,这并不能得到您想要的答案。

        5
  •  1
  •   Eduard Okhvat    8 年前

    所有这些都在心里。
    从SQL Server 2012开始(可能是2008年?),有列 数据库数据库 在里面 sys.dm_exec_会话 .
    它使我们可以方便地计算每个数据库的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;
    
        6
  •  0
  •   Lieven Keersmaekers    15 年前

    看一看 SQL Sentry . 它能满足你所有的需要,还有更多。

    当做, 利芬

        7
  •  0
  •   Guy    15 年前

    您看过SQL事件探查器吗?

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

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

    如果同时监视PerfMon计数器(将数据记录到SQL数据库),并对SQL事件探查器(记录到数据库)执行同样的操作,则 可以 能够将两者联系起来。

    即使如此,它也应该给你足够的线索,让你知道哪个数据库值得更详细地研究。然后,只对该数据库ID执行同样的操作,并查找最昂贵的SQL/存储过程。

        8
  •  0
  •   Matt user129975    9 年前

    请检查此查询:

    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