1 sql-server-2008 sql-server profiler
我们有一个带有 15 个数据库的 SQL Server。这被每个数据库中的许多用户同时使用。最近,我们开始从该服务器收到高 CPU 警报。当警报出现时,我可以跟踪到确切的用户和查询。
我们无法在此服务器上打开 SQL Server Profiler。我想知道我们是否可以使用任何脚本获取有关在任何数据库(导致高 CPU)中运行的历史昂贵查询的信息。例如 - 我需要过去 4 小时内最昂贵的查询以及数据库名称和用户名。
不,SQL Server 不跟踪查询的单个出现,原因与您不想运行探查器的原因相同:不断跟踪会对服务器产生重大的性能影响,而 Microsoft 最不想做的就是打开高- 大多数人很少或从不使用的成本诊断。无论如何,Profiler 绝对是您要用于此目的的最后一个工具,因为它是最糟糕的罪犯。服务器端跟踪的重量要轻得多,但您还应该查看扩展事件,甚至可能是 3rd 方监控工具 - 我为一个此类工具的供应商工作,并很乐意在那里为您提供指导。
同时,您可以使用和 之类的DMV汇总跟踪昂贵的查询。这是Glenn Berry 的诊断查询中的一个过程,它获取特定数据库的前 25 个消耗 CPU 的存储过程:sys.dm_exec_procedure_statssys.dm_exec_query_stats
SELECT TOP(25) p.name AS [SP Name], qs.total_worker_time AS [TotalWorkerTime],
qs.total_worker_time/qs.execution_count AS [AvgWorkerTime], qs.execution_count,
ISNULL(qs.execution_count/DATEDIFF(Second, qs.cached_time, GETDATE()), 0) AS [Calls/Second],
qs.total_elapsed_time, qs.total_elapsed_time/qs.execution_count
AS [avg_elapsed_time], qs.cached_time
FROM sys.procedures AS p WITH (NOLOCK)
INNER JOIN sys.dm_exec_procedure_stats AS qs WITH (NOLOCK)
ON p.[object_id] = qs.[object_id]
WHERE qs.database_id = DB_ID()
ORDER BY qs.total_worker_time DESC OPTION (RECOMPILE);
Run Code Online (Sandbox Code Playgroud)
sys.dm_exec_query_stats如果您有很多即席查询,您可以做类似的事情。例如:
SELECT TOP(25) SUBSTRING(t.text, (qs.statement_start_offset/2)+1,
((CASE qs.statement_end_offset
WHEN -1 THEN DATALENGTH(t.text)
ELSE qs.statement_end_offset
END - qs.statement_start_offset)/2) + 1) AS statement_text,
qs.total_worker_time/qs.execution_count AS [AvgWorkerTime], qs.execution_count,
ISNULL(qs.execution_count/DATEDIFF(Second,qs.creation_time,GETDATE()),0) AS [Calls/Second],
qs.total_elapsed_time, qs.total_elapsed_time/qs.execution_count AS [avg_elapsed_time]
FROM sys.dm_exec_query_stats AS qs WITH (NOLOCK)
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS t
ORDER BY AvgWorkerTime DESC OPTION (RECOMPILE);
Run Code Online (Sandbox Code Playgroud)
请注意,这些 DMV 不会在服务重启和其他一些事件之外保留数据,因此您可能没有预期的历史记录。