Encontrei as seguintes consultas para detectar o uso da CPU pelo banco de dados, mas elas estão mostrando resultados diferentes:
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);
A consulta acima informa que o problema é com um dos meus bancos de dados (quase 96%).
E a consulta abaixo informa que o problema é com os bancos de dados mestre e de distribuição (cerca de 90%):
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
Eu verifiquei se o sys.sysprocesses
está decpreated. Isso significa que os resultados da segunda consulta estão errados?
Embora eu, como @Thomas, concorde completamente com @Aaron nos comentários sobre a questão sobre as preocupações do "uso da CPU por banco de dados" ser preciso ou útil, posso pelo menos responder à pergunta sobre por que essas duas consultas são tão diferente. E a razão pela qual eles são diferentes indicará qual é mais preciso, embora esse nível mais alto de precisão ainda seja relativo ao que é especificamente impreciso, portanto, ainda não é realmente preciso ;-).
A primeira consulta usa sys.dm_exec_query_stats para obter informações da CPU (ou seja,
total_worker_time
). Se você for para a página vinculada que é a documentação do MSDN para esse DMV, verá uma introdução curta de 3 frases e 2 dessas frases nos dão a maior parte do que precisamos para entender o contexto dessas informações ("quão confiável é" e "como se compara asys.sysprocesses
"). Essas duas frases são:A primeira frase, "Retorna estatísticas de desempenho agregadas ", nos diz que as informações neste DMV (assim como vários outros) são cumulativas e não específicas apenas para consultas que estão em execução no momento. Isso também é indicado por um campo nesse DMV que não faz parte da consulta na Pergunta,
execution_count
, que novamente mostra que se trata de dados cumulativos. E é bastante útil que esses dados sejam cumulativos, pois você pode obter médias, etc., dividindo algumas das métricas peloexecution_count
.A segunda frase, "planos sendo removidos do cache também são removidos deste DMV", indica que não é uma imagem completa, especialmente se o servidor já tiver um cache de plano bastante cheio e estiver sob carga e, portanto, estiver expirando planos com certa frequência. Além disso, a maioria dos DMVs é redefinida quando o servidor é redefinido para que não sejam um histórico verdadeiro, mesmo que essas linhas não tenham sido removidas quando os planos expirarem.
Agora vamos contrastar o acima com
sys.sysprocesses
. Essa visualização do sistema mostra apenas o que está sendo executado no momento, assim como a combinação de sys.dm_exec_connections , sys.dm_exec_sessions e sys.dm_exec_requests (que é indicado na página vinculada parasys.dm_exec_sessions
). Esta é uma visão totalmente diferente do servidor em comparação com osys.dm_exec_query_stats
DMV que mantém os dados mesmo após a conclusão do processo. Ou seja, em relação ao "os resultados da segunda consulta estão errados?" questão, eles não estão errados, eles apenas dizem respeito a um aspecto diferente (ou seja, período de tempo) das estatísticas de desempenho.Portanto, a consulta usando
sys.sysprocesses
está apenas olhando para "agora". E a consulta usandosys.dm_exec_query_stats
está olhando principalmente (talvez) o que aconteceu desde a última reinicialização do serviço SQL Server (ou obviamente reinicialização do sistema). Para análise geral de desempenho, parece quesys.dm_exec_query_stats
é muito melhor, mas, novamente, descarta informações úteis o tempo todo. E, em ambos os casos, você também precisa considerar os pontos feitos por @Aaron nos comentários da pergunta (já removidos) em relação à precisão do valor "database_id" em primeiro lugar (ou seja, reflete apenas o banco de dados ativo que iniciou o código , não necessariamente onde o "problema" está ocorrendo).Mas, se você apenas precisa/quer ter uma noção do que está acontecendo agora em todos os bancos de dados, possivelmente porque as coisas estão desacelerando agora, é melhor usar a combinação de
sys.dm_exec_connections
,sys.dm_exec_sessions
esys.dm_exec_requests
(e não o obsoletosys.sysprocesses
). Apenas tenha em mente que você está procurando por consultas , não bancos de dados , porque as consultas podem se unir em vários bancos de dados, incluir UDFs de um ou mais bancos de dados etc.EDIT:
Se a preocupação geral for reduzir os altos consumidores de CPU, procure as consultas que estão ocupando mais CPU, porque os bancos de dados não ocupam a CPU (procurar por banco de dados pode funcionar em uma empresa de hospedagem onde cada banco de dados é isolado e propriedade de um cliente diferente).
A consulta a seguir ajudará a identificar consultas com uso médio de CPU alto. Ele condensa os dados no DMV query_stats, pois esses registros podem mostrar a mesma consulta (sim, o mesmo subconjunto do lote de consultas) várias vezes, cada uma com um plano de execução diferente.
Ajustei a consulta para divisão por 0 erros e otimizei os nomes das colunas para copiar/colar no Excel.
Gostei tanto da consulta da CPU
sys.dm_exec_query_stats
que a estendi. Ele ainda é classificado por CPU, mas adicionei outros totais e porcentagens para obter um perfil de servidor melhor. Isso copia bem no Excel e com formatação condicional de cores nas colunas Porcentagem, os piores números se destacam bem. Usei a 'Graded Color Scale' com 3 cores; uma cor rosa para valores altos, amarelo para médio, verde para baixo.Eu adicionei um rótulo para
database id 32676
o qual é o banco de dados de recursos SQL interno. Eu converto o tempo de CPU e Duração em Horas para ter uma melhor noção do uso do tempo.Descobrimos que usar o Query Store é um excelente ponto de partida na investigação de consumidores de CPU do servidor. Caso o QS esteja habilitado em todos os bancos de dados de usuários, você obterá uma estimativa bastante precisa da distribuição média de CPU entre eles durante algum período de tempo.
Por exemplo, a consulta abaixo retorna informações sobre consumidores de CPU da semana passada: