您可以使用 DMV 识别成本高昂的查询(以及与它们关联的数据库),例如来自这篇 TechNet 文章 http://msdn.microsoft.com/en-us/magazine/cc135978.aspx:
SELECT TOP 50
[Average CPU used] = total_worker_time / qs.execution_count,
[Total CPU used] = total_worker_time,
[Execution count] = qs.execution_count,
[Individual Query] = SUBSTRING (qt.text,qs.statement_start_offset/2,
(CASE WHEN qs.statement_end_offset = -1
THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2
ELSE qs.statement_end_offset END -
qs.statement_start_offset)/2)
,[Parent Query] = qt.text
,DatabaseName = DB_NAME(qt.dbid)
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt
ORDER BY [Average CPU used] DESC;
这些将告诉您有关重型查询的信息,但不幸的是,它不会查明可能具有大量小型查询的数据库,这些小型查询单独使用少量 CPU,但总体使用大量 CPU。您可以使用此查询来做到这一点来自 Glenn Allan Berry 的 DMV 查询 http://sqlserverperformance.wordpress.com/tag/dmv-queries/:
WITH DB_CPU_Stats
AS
(SELECT DatabaseID, DB_Name(DatabaseID) AS [DatabaseName],
SUM(total_worker_time) AS [CPU_Time_Ms]
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY (SELECT CONVERT(int, value) AS [DatabaseID]
FROM sys.dm_exec_plan_attributes(qs.plan_handle)
WHERE attribute = N'dbid') AS F_DB
GROUP BY DatabaseID)
SELECT ROW_NUMBER() OVER(ORDER BY [CPU_Time_Ms] DESC) AS [row_num],
DatabaseName, [CPU_Time_Ms],
CAST([CPU_Time_Ms] * 1.0 / SUM([CPU_Time_Ms])
OVER() * 100.0 AS DECIMAL(5, 2)) AS [CPUPercent]
FROM DB_CPU_Stats
WHERE DatabaseID > 4 -- system databases
AND DatabaseID <> 32767 -- ResourceDB
ORDER BY row_num OPTION (RECOMPILE);
这些查询都无法识别运行它们的应用程序,并且使用的 DMV 不会存储该信息(您必须捕获实际的查询并记下 sys.dm_exec_sessions 中的应用程序名称,或查看跟踪)。
当然,您可以使用市场上的各种第 3 方性能工具自动执行此工作(免责声明:我为其中之一的 SQL Sentry 工作,该工具生产绩效顾问 http://www.sqlsentry.net/performance-advisor/sql-server-performance.asp,它执行上述所有操作,包括跟踪高成本查询并维护有关它们在哪个数据库中运行以及哪个应用程序调用它们的信息)。