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

数据库的CPU利用率?

  •  31
  • Portman  · 技术社区  · 17 年前

    是否有可能获得CPU利用率的明细 按数据库 ?

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

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

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

    某种程度上。查看此查询:

    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中,微软引入了性能管理和应用程序管理功能,使我们能够将单个数据库打包到可分发和可部署的DAC包中,这些功能有望使管理单个数据库及其应用程序的性能变得更加容易。然而,它仍然没有达到你想要的效果。

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

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

        2
  •  15
  •   Adam    17 年前

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

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

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

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

        3
  •  6
  •   friism    13 年前

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

    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    16 年前

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

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

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

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

        5
  •  1
  •   Eduard Okhvat    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
    
        6
  •  0
  •   Lieven Keersmaekers    16 年前

    考虑到以上所述。
    从SQL Server 2012(可能是2008?)开始,有一列 数据库id 在……里面 sys.dmexec_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;
    
        7
  •  0
  •   Guy    16 年前

    看一看 SQL Sentry 它能满足你的所有需求,甚至更多。

    当做, 利芬

        8
  •  0
  •   Matt user129975    10 年前

    你看过SQL分析器吗?

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

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

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

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

    推荐文章