@Thomas와 마찬가지로 "데이터베이스 당 CPU 사용량"이 정확하거나 유용하다는 문제에 대한 질문에 대한 의견에서 @Aaron에 전적으로 동의하지만 적어도 두 쿼리가 왜 그렇게되는지에 대한 질문에 대답 할 수 있습니다. 다른. 그리고 그들이 다른 이유는 어느 것이 더 정확한지를 나타내지 만, 더 높은 수준의 정확도는 여전히 정확하지 않은 정확도에 비해 여전히 정확하지 않으므로 ;-).
첫 번째 쿼리는 sys.dm_exec_query_stats 를 사용 하여 CPU 정보 (예 :) 를 가져옵니다 total_worker_time
. 해당 DMV에 대한 MSDN 문서 인 링크 된 페이지로 이동하면 짧은 3 문장 소개와 2 문장의 문장이이 정보의 맥락을 이해하는 데 필요한 대부분의 정보를 제공합니다 ( "얼마나 믿을만한가?" 그리고 "어떻게 비교 sys.sysprocesses
"). 이 두 문장은 다음과 같습니다.
SQL Server에서 캐시 된 쿼리 계획에 대한 집계 성능 통계를 반환합니다. ... 계획이 캐시에서 제거되면 해당 행이이보기에서 제거됩니다.
첫 번째 문장 인 " 집계 성능 통계를 리턴 합니다"는이 DMV의 정보 (여러 다른 것과 마찬가지로)가 누적되며 현재 실행중인 쿼리에만 국한되지 않음을 알려줍니다. 이것은 또한 질문의 쿼리에 포함되지 않은 DMV의 필드로 표시되며 execution_count
이는 다시 누적 데이터임을 나타냅니다. 그리고 일부 메트릭을로 나누어 평균 등을 얻을 수 있으므로이 데이터를 누적하는 것이 매우 편리합니다 execution_count
.
두 번째 문장 인 "캐시에서 제거되는 계획도이 DMV에서 제거됩니다"는 서버가 이미 전체 계획 캐시를 가지고 있고로드 중이므로 계획이 만료되는 경우 전체 그림이 아님을 나타냅니다. 다소 자주. 또한 대부분의 DMV는 서버가 재설정 될 때 재설정되므로 계획이 만료 될 때 이러한 행이 제거되지 않은 경우에도 실제 히스토리가 아닙니다.
위와를 대조해 봅시다 sys.sysprocesses
. 이 시스템보기는 sys.dm_exec_connections , sys.dm_exec_sessions 및 sys.dm_exec_requests 의 조합 (현재 링크 된 페이지에 표시 sys.dm_exec_sessions
) 과 같이 현재 실행중인 항목 만 표시합니다 . 이것은 sys.dm_exec_query_stats
프로세스가 완료된 후에도 데이터를 보유하는 DMV 와 비교할 때 서버에 대해 완전히 다른 관점입니다 . "두 번째 쿼리의 결과가 잘못 되었습니까?"와 관련하여 의미합니다. 문제는 틀린 것이 아니라 단지 성능 통계의 다른 측면 (즉, 시간대)과 관련이 있다는 것입니다.
따라서 사용하는 쿼리 sys.sysprocesses
는 "지금"만보고 있습니다. 그리고 사용하는 쿼리 는 SQL Server 서비스를 마지막으로 다시 시작한 이후 (또는 분명히 시스템을 재부팅 한 후) 발생한 일 sys.dm_exec_query_stats
을 주로 보고 있습니다. 일반적인 성능 분석의 경우 sys.dm_exec_query_stats
훨씬 나은 것으로 보이지만 다시 유용한 정보를 항상 삭제합니다. 그리고 두 경우 모두 처음에 "database_id"값의 정확성과 관련하여 @Aaron이 질문 설명에서 삭제 한 점을 고려해야합니다 (즉, 코드를 시작한 활성 DB 만 반영 함). "문제"가 반드시 발생하는 것은 아닙니다.)
당신은 단지 필요하지만, / 일 지금 둔화되는 가능성이 있기 때문에, 당신의 조합을 사용하는 것이 더 낫다, 모든 데이터베이스에서 지금 무슨 일이 일어나고 있는지의 감각을 얻고 싶은 sys.dm_exec_connections
, sys.dm_exec_sessions
그리고 sys.dm_exec_requests
(그리고 사용되지 않는 sys.sysprocesses
). 쿼리는 여러 데이터베이스에서 결합 될 수 있고 하나 이상의 데이터베이스의 UDF 등을 포함 할 수 있으므로 데이터베이스가 아닌 쿼리를 찾고 있습니다.
편집 :
전반적인 관심사가 CPU 소비를 줄이면 데이터베이스가 실제로 CPU를 차지하지 않기 때문에 CPU를 가장 많이 차지하는 쿼리를 찾으십시오 (데이터베이스가 분리되어 있고 각 데이터베이스가 격리되어있는 호스팅 회사에서 데이터베이스별로 작동 할 수 있음) 다른 고객이 소유).
다음 쿼리는 평균 CPU 사용량이 높은 쿼리를 식별하는 데 도움이됩니다. 이러한 레코드는 각각 다른 실행 계획을 가진 동일한 쿼리 (예, 쿼리 배치의 동일한 서브 세트)를 여러 번 표시 할 수 있으므로 query_stats DMV의 데이터를 압축합니다.
;WITH cte AS
(
SELECT stat.[sql_handle],
stat.statement_start_offset,
stat.statement_end_offset,
COUNT(*) AS [NumExecutionPlans],
SUM(stat.execution_count) AS [TotalExecutions],
((SUM(stat.total_logical_reads) * 1.0) / SUM(stat.execution_count)) AS [AvgLogicalReads],
((SUM(stat.total_worker_time) * 1.0) / SUM(stat.execution_count)) AS [AvgCPU]
FROM sys.dm_exec_query_stats stat
GROUP BY stat.[sql_handle], stat.statement_start_offset, stat.statement_end_offset
)
SELECT CONVERT(DECIMAL(15, 5), cte.AvgCPU) AS [AvgCPU],
CONVERT(DECIMAL(15, 5), cte.AvgLogicalReads) AS [AvgLogicalReads],
cte.NumExecutionPlans,
cte.TotalExecutions,
DB_NAME(txt.[dbid]) AS [DatabaseName],
OBJECT_NAME(txt.objectid, txt.[dbid]) AS [ObjectName],
SUBSTRING(txt.[text], (cte.statement_start_offset / 2) + 1,
(
(CASE cte.statement_end_offset
WHEN -1 THEN DATALENGTH(txt.[text])
ELSE cte.statement_end_offset
END - cte.statement_start_offset) / 2
) + 1
)
FROM cte
CROSS APPLY sys.dm_exec_sql_text(cte.[sql_handle]) txt
ORDER BY cte.AvgCPU DESC;
AvgCPU
밀리 초 단위로?