SQL CPU Current% 按數據庫
在問題中如何獲取特定實例的數據庫的 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 的全域視圖,如果:
- 您的程式碼被完全隔離到每個單獨的數據庫中,並且不執行任何跨數據庫查詢。
- 登錄或者直接進入程式碼所在的數據庫,或者執行儲存過程,或者至少
USE
在執行任何臨時查詢/動態 SQL 之前發出一條語句。- 該程式碼要麼不使用 tempdb / 臨時表 / 表變數 / 快照隔離,要麼它們都以大致相同的程度使用這些東西(想法是取消
tempdb
使用)我們有微服務架構,沒有跨數據庫連接,每個儲存過程查詢都正確設置了初始數據庫,沒有臨時查詢,我們只想要每個數據庫 cpu% 的基線測量,不推薦使用 sys.sysprocesses
在這種情況下,您可能可以使用這兩種方法:
sys.dm_exec_query_stats
(如問題中的連結答案所示 - 只需在database_id
其中添加列)和:
sys.dm_exec_connections
、sys.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;
**請注意:**這顯示了現有會話的統計資訊。如果您的應用程序使用連接池,那麼會話將停留一段時間,您將獲得更多有用的資訊(在“已完成”列中)。如果你不使用連接池,這將是有限的,因為會話會在你獲得有用的指標之前消失。問題是目前執行的程序在
requests
DMV 中,並且sessions
DMV 包含已完成請求的資訊。如果是這種情況,那麼添加sys.dm_exec_requests
會有所幫助,因為這將顯示真正的“目前”活動,但同樣,對於持續時間在(希望)亞秒範圍內的查詢,這不會顯示您的那種趨勢需要做出決定,這就是為什麼您需要這個和DMVdm_exec_query_stats
查詢。**此外,**我的測試似乎表明,雖然“目前”列
ExecutingTotalElapsedTime
和ExecutingTotalLogicalReads
確實匯總到與預期相同的度量的會話“總”列中,TotalCpuTime
但請求的列卻沒有。意思是,如果請求顯示 CPU 時間為 300,然後結束(並轉到NULL
),但 Session 仍然可以看到,不要期望CompletedTotalCpuTime
Session 的更新列比請求完成之前多 300。有時它只會上升一點點。