【问题标题】:CPU utilization by database?数据库的CPU利用率?
【发布时间】:2010-09-06 22:27:43
【问题描述】:

是否可以按数据库获得 CPU 利用率细分?

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

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

【问题讨论】:

    标签: sql-server monitoring


    【解决方案1】:

    考虑到以上所有内容。
    从 SQL Server 2012 开始(可能是 2008 年?),sys.dm_exec_sessions 中有列 database_id
    它使我们可以轻松计算 当前连接 会话的每个数据库的 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;
    

    【讨论】:

      【解决方案2】:

      请检查此查询:

      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
      

      【讨论】:

        【解决方案3】:

        有点。看看这个查询:

        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 日更新,包括总数而不是平均值。

        【讨论】:

        • 原谅我的无知,但是AvgCPU和AvgDuration的单位是什么?
        • 毫秒数 - CPU 时间毫秒数和持续时间毫秒数。它们可能不同,因为查询可以等待 IO、锁、客户端等。我将修改查询以获取总数。 (我想说英尺磅,但我无法保持虚拟的直面。)
        【解决方案4】:

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

        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
        

        【讨论】:

          【解决方案5】:

          您看过 SQL 分析器吗?

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

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

          如果您同时监控 PerfMon 计数器(将数据记录到 SQL 数据库),并对 SQL Profiler 执行相同操作(记录到数据库),您也许能够关联两个在一起。

          即便如此,它也应该为您提供足够的线索,让您了解哪个 DB 值得更详细地研究。然后,仅使用该数据库 ID 再次执行相同操作,并查找最昂贵的 SQL/存储过程。

          【讨论】:

            【解决方案6】:

            看看SQL Sentry。它可以满足您的所有需求以及更多功能。

            问候, 利文

            【讨论】:

              【解决方案7】:

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

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

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

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

              【讨论】:

                【解决方案8】:

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

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

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

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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2019-11-22
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-09-30
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多