Sql-Server

SQL CPU Current% 按數據庫

  • January 23, 2018

在問題中如何獲取特定實例的數據庫的 CPU 使用率?Solomon 說:使用 sys.sysprocesses 的查詢現在只是查看。使用 sys.dm_exec_query_stats 的查詢主要查看自上次重新啟動 SQL Server 服務或顯然是系統重新啟動以來發生的情況。

Microsoft 聲明 sysprocesses 已棄用。

在沒有棄用系統程序的情況下找到目前 CPU% 的正確方法是什麼,我對查看單個查詢不感興趣。我們只需要目前狀態下每個數據庫的通用級別性能指標。我們有微服務架構,所以沒有跨數據庫連接,只有自數據庫查詢,沒有 ad-hoc。每個查詢都正確設置了 InitialDB,不使用 masterdb、tempdb。

DECLARE @total INT
SELECT @total=sum(cpu) FROM sys.sysprocesses sp (NOLOCK)
   join sys.sysdatabases sb (NOLOCK) ON sp.dbid = sb.dbid

SELECT sb.name 'database', @total 'system cpu', SUM(cpu) 'database cpu', CONVERT(DECIMAL(4,1), CONVERT(DECIMAL(17,2),SUM(cpu)) / CONVERT(DECIMAL(17,2),@total)*100) '%'
FROM sys.sysprocesses sp (NOLOCK)
JOIN sys.sysdatabases sb (NOLOCK) ON sp.dbid = sb.dbid
--WHERE sp.status = 'runnable'
GROUP BY sb.name
ORDER BY CONVERT(DECIMAL(4,1), CONVERT(DECIMAL(17,2),SUM(cpu)) / CONVERT(DECIMAL(17,2),@total)*100) desc

如果我想更好地了解目前正在發生的事情,使用“sys.dm_exec_connections、sys.dm_exec_sessions 和 sys.dm_exec_requests 的組合”的目前度量查詢是什麼。通過數據庫測量目前的 CPU%?

如前所述,沒有辦法獲得真正準確的每個數據庫 CPU 百分比,因為這不是 SQL Server 的工作方式。列並返回“活動”數據庫database_id的ID。“活動”的數據庫是反映臨時查詢/動態 SQL 的最新語句的數據庫,或者如果正在執行儲存過程,則儲存過程所在的數據庫(我假設觸發器屬於此類)好吧,因為它們本質上是基於事件的儲存過程)。而且,如果一個儲存過程在另一個數據庫中執行另一個,“活動”數據庫是反映目前執行的儲存過程所在位置的那個(即處理嵌套儲存過程時的最內層)。sys.dm_exec_sessions``sys.dm_exec_requests``USE

因此,請考慮以下事項:

-- log into [master]

USE [msdb];
CREATE TABLE #TempTable ([Col1] INT, [Col2] INT);
INSERT INTO #TempTable ([Col1], [Col2])
  SELECT [object_id], [column_id]
  FROM   [sys].[all_columns];


USE [Database1];
EXEC [Database2].[dbo].[StoredProc];

假設“Database2.dbo.StoredProc”定義如下:

CREATE PROCEDURE dbo.StoredProc
AS
SET NOCOUNT ON;

INSERT INTO [Database8].[dbo].[TableWithInsertTriggerToLogIntoDatabase9](Col1, Col2, Col3)
 SELECT  (tmp.[Col1] * tmp.[Col2]) AS [WhatEvs],
         [Database3].[dbo].NevrFastTsqlUDF(tmp.[Col1])
                                   AS [UnnecessaryEncapsulationOfSimpleFormula],
         [Database4].[dbo].[SQLCLR_UDF_with_external_connection_to_Database7](tvf.[Col3])
                                   AS [Wow]
 FROM    #TempTable tmp
 LEFT JOIN  [Database5].[dbo].[LargeTable] lt
        ON  lt.[Col1] = tmp.[Col1]
 OUTER APPLY  [Database6].[dbo].[TsqlTVF](lt.[Col2]) tvf
 WHERE   tmp.[Col1] > 0;

這是一個非常複雜的範例,但它旨在表明有幾個領域可能會導致性能下降。哪個數據庫將反映在 DMV 中?最有可能是“Database2”,因為它是儲存過程存在的地方,即使它查詢/使用的表或函式都不存在那裡。但是,如果您要INSERT...SELECT在“Database1”中執行與臨時查詢相同的操作(而不是執行儲存過程),那麼將反映在 DMV 中的將是“Database1”。

公平地說,您可能會得到一個合理的 per-DB CPU 的全域視圖,如果

  1. 您的程式碼被完全隔離到每個單獨的數據庫中,並且不執行任何跨數據庫查詢。
  2. 登錄或者直接進入程式碼所在的數據庫,或者執行儲存過程,或者至少USE在執行任何臨時查詢/動態 SQL 之前發出一條語句。
  3. 該程式碼要麼不使用 tempdb / 臨時表 / 表變數 / 快照隔離,要麼它們都以大致相同的程度使用這些東西(想法是取消tempdb使用)

我們有微服務架構,沒有跨數據庫連接,每個儲存過程查詢都正確設置了初始數據庫,沒有臨時查詢,我們只想要每個數據庫 cpu% 的基線測量,不推薦使用 sys.sysprocesses

在這種情況下,您可能可以使用這兩種方法:

  • sys.dm_exec_query_stats(如問題中的連結答案所示 - 只需在database_id其中添加列)

和:

  • sys.dm_exec_connectionssys.dm_exec_sessions和的組合sys.dm_exec_requests。加入他們所有人session_id。但是,您可能不需要sys.dm_exec_connections從其他兩個開始:
USE [master];
SELECT DB_NAME(sess.[database_id]) AS [DatabaseName],
      SUM(sess.[cpu_time]) AS [CompletedTotalCpuTime],
      SUM(sess.total_elapsed_time) AS [CompletedTotalElapsedTime],
      SUM(sess.logical_reads) AS [CompletedTotalLogicalReads],
      '---' AS [---],
      SUM(req.[cpu_time]) AS [ExecutingTotalCpuTime],
      SUM(req.[total_elapsed_time]) AS [ExecutingTotalElapsedTime],
      SUM(req.[logical_reads]) AS [ExecutingTotalLogicalReads],
      SUM(req.[wait_time]) AS [ExecutingTotalWaitTime]
FROM sys.dm_exec_sessions sess
LEFT JOIN  sys.dm_exec_requests req
      ON  req.[session_id] = sess.[session_id]
WHERE sess.is_user_process = 1
AND   sess.[program_name] NOT LIKE N'Microsoft SQL Server Management Studio%'
GROUP BY sess.[database_id]
ORDER BY [CompletedTotalCpuTime] DESC;

**請注意:**這顯示了現有會話的統計資訊。如果您的應用程序使用連接池,那麼會話將停留一段時間,您將獲得更多有用的資訊(在“已完成”列中)。如果你不使用連接池,這將是有限的,因為會話會在你獲得有用的指標之前消失。問題是目前執行的程序在requestsDMV 中,並且sessionsDMV 包含已完成請求的資訊。如果是這種情況,那麼添加sys.dm_exec_requests會有所幫助,因為這將顯示真正的“目前”活動,但同樣,對於持續時間在(希望)亞秒範圍內的查詢,這不會顯示您的那種趨勢需要做出決定,這就是為什麼您需要這個和DMVdm_exec_query_stats查詢。

**此外,**我的測試似乎表明,雖然“目前”列ExecutingTotalElapsedTimeExecutingTotalLogicalReads確實匯總到與預期相同的度量的會話“總”列中,TotalCpuTime但請求的列卻沒有。意思是,如果請求顯示 CPU 時間為 300,然後結束(並轉到NULL),但 Session 仍然可以看到,不要期望CompletedTotalCpuTimeSession 的更新列比請求完成之前多 300。有時它只會上升一點點。

引用自:https://dba.stackexchange.com/questions/196013