Alto uso da CPU no servidor SQL - Consultas lentas [fechadas]

11

Nosso MS SQL Server está usando cerca de 95% da energia da CPU.

Após a reinicialização de um servidor (hardware) ou do Serviço SQL, o uso é de 0% e aumenta lentamente ao longo de 1 a 3 dias. Dependendo de quanto é usado.

Quando ultrapassa os 80%, todas as consultas são extremamente lentas.

Nosso site está lidando com muitas consultas grandes; portanto, algumas delas levam de 45 a 60 segundos. Após uma reinicialização (uso da CPU menor que 80%), leva de 11 a 20 segundos para a mesma consulta.


Como posso consertar isso? Li online que as máscaras de afinidade podem ajustar o uso da CPU, mas as configurações de afinidade estão desabilitadas. Eu não posso mudá-los. Isso é porque eu tenho apenas 1 processador?

Existem muitos truques relacionados às consultas em si, mas nossos sites e serviços são muito grandes e há muito a mudar.

A maioria deles já está muito bem otimizada.


Não consigo continuar reiniciando o serviço SQL, mesmo que demore apenas 2 segundos, porque como temos um serviço de alarme que permite que as pessoas liguem e gravem uma mensagem, um grupo selecionado será chamado e ouvirá a mensagem gravada.

Este sistema é usado por centenas de equipes de Pesquisa e Salvamento e, se o Serviço SQL reiniciar durante um alarme, ele será encerrado e a pessoa que o chamou não será notificada.


Eu procurei por todo o lugar, mas não encontrei nada, exceto as coisas sobre "Affinity Masks", que não posso mudar.

Deve haver uma maneira de limpar o cache da CPU, sem encerrar as consultas atuais ... certo?


SQL: Microsoft SQL Server 11.0.2100.60
OS: Windows Server 2012 x64
Processor: 2.30 GHz
RAM: 4.00 GB
Levi Johansen
fonte
Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Paul White 9

Respostas:

7

Esta é uma possibilidade, mas você pode dar uma olhada na sua configuração de parametrização forçada. Se você estiver vendo um grande número de planos de consulta quando o desempenho é ruim, suas consultas não estão sendo armazenadas em cache da maneira que você espera e as consultas demoram muito tempo para varrer o cache para verificar se já existe um plano. Se a limpeza do cache resolver esse problema, convém alterar a configuração de parametrização forçada. Você pode limpar o cache usando:

DBCC FREEPROCCACHE

Você pode verificar para ver qual é a configuração de parametrização forçada se estiver limpando o cache trabalhado por:

SELECT name
     , is_parameterization_forced
  FROM sys.databases;

Provavelmente, isso está definido como 0, o padrão. Se eles desejam, você pode definir isso como verdadeiro, fazendo:

ALTER DATABASE [database_name] SET PARAMETERIZATION FORCED;

Isso deve ser feito em um ambiente de desenvolvimento primeiro e veja se isso afeta negativamente o banco de dados de outras maneiras. Pode ser revertido usando:

ALTER DATABASE [database_name] SET PARAMETERIZATION SIMPLE;
Drew Leffelman
fonte
5
Observe que liberar o cache do procedimento pode realmente causar um grande aumento na CPU - já que todas as consultas agora terão que recompilar seus planos de execução.
Aaron Bertrand
18

O Affinity não "ajusta o uso da CPU" (por exemplo, no caso em que as CPUs executam menos trabalho), permite desativar uma CPU (talvez disponibilizá-la para outra instância na mesma máquina) ou definir uma CPU para ajuda apenas com E / S. Mesmo se você tivesse várias CPUs, você não seria capaz de usar a primeira para ajudar com sua meta, e é impossível adivinharmos sobre a segunda, porque não sabemos o que está aumentando o uso da CPU. Pode ser devido à indexação extremamente ruim, compilações excessivas, abundância de UDFs escalares, e / S debulhando, quem sabe? (E a razão pela qual a E / S pode ser a causa é que, se o seu banco de dados for maior que 3 GB ou mais, ele terá que trocar constantemente os dados dentro e fora da memória do buffer pool, e isso afeta a CPU.)

O cache da CPU também é uma toca de coelho que você não precisa descer. Eu duvido muito que sua CPU esteja atingindo 95% por causa de problemas com o cache da CPU.

Para ajudar a diminuir a fonte de pressão da CPU e supondo que você esteja usando procedimentos armazenados, você pode dar uma olhada nesta consulta de diagnóstico de Glenn Berry ( originária daqui ) - certifique-se de executá-la no contexto do banco de dados correto:

-- Top Cached SPs By Total Worker time (SQL Server 2012). 
-- Worker time relates to CPU cost  (Query 44) (SP Worker Time)

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);

-- This helps you find the most expensive cached stored procedures from a CPU perspective
-- You should look at this if you see signs of CPU pressure

Se você não estiver usando procedimentos armazenados, este exemplo de John Samson pode ajudar a isolar consultas ad hoc ( originárias daqui ):

SELECT TOP (25)
    qs.sql_handle,
    qs.execution_count,
    qs.total_worker_time AS Total_CPU,
    total_CPU_inSeconds = --Converted from microseconds
    qs.total_worker_time/1000000,
    average_CPU_inSeconds = --Converted from microseconds
    (qs.total_worker_time/1000000) / qs.execution_count,
    qs.total_elapsed_time,
    total_elapsed_time_inSeconds = --Converted from microseconds
    qs.total_elapsed_time/1000000,
    st.text,
    qp.query_plan
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
CROSS apply sys.dm_exec_query_plan (qs.plan_handle) AS qp
ORDER BY qs.total_worker_time DESC OPTION (RECOMPILE);

Você também pode dar uma olhada no sp_WhoIsActive de Adam Machanic , um procedimento armazenado que pode analisar rapidamente todas as consultas em execução no momento e permitir que você as classifique da maneira que desejar (por exemplo, no seu caso @sort_order = '[CPU] DESC').

Porém, a primeira coisa que eu faria - principalmente se isso é realmente essencial para as equipes de busca e resgate - é comprar um hardware melhor. Você deve ter mais CPUs e mais RAM para atender ao seu aplicativo. Você também precisa absolutamente de uma melhor disponibilidade alta (por exemplo, clustering, espelhamento ou grupos de disponibilidade). Não há razão para que a reinicialização de uma máquina física deixe seu aplicativo completamente offline - temos soluções melhores para esse problema. E, finalmente, presumo que esse "servidor" tenha apenas uma unidade de disco giratório. Isso significa que todas as E / S - do SO, dos arquivos de dados, arquivos de log, tempdb etc. do SQL Server, passam por um único controlador e compartilham atividades de leitura / gravação em uma única unidade. Obtenha mais discos. Obtenha SSDs se / onde você puder. Use RAID e tente espalhar a E / S o máximo possível.

Dito isso, jogar o hardware no problema não será a única parte da correção. Você precisa isolar exatamente o que está causando o uso excessivo da CPU e atacar esses problemas, independentemente do hardware em que está.

Consulte também esta pergunta StackOverflow para outras idéias:

/programming/945063/how-do-i-find-out-what-is-hammering-my-sql-server

Aaron Bertrand
fonte
0

As sugestões a seguir são um 'tiro no escuro' porque não consigo ver o código real.

O primeiro é que um SP pode estar abrindo cursores e deixando-os abertos. Leia os Cursores, particularmente Fechar e Desalocar. Alguém pode estar fechando, mas não desalocando cursores. O comportamento pode ter sido alterado devido à atualização; 2012 pode tratar os cursores restantes de maneira diferente do 2008 R2.

O segundo é que pode haver bloqueios de tabela que não são limpos. Novamente, estou longe, não sei dizer, mas isso sugere que alguém cria uma tabela temporária global após uma 'transação inicial' e nenhuma 'transação final' é executada ou o procedimento armazenado falha deixando um bloqueio tabela ocupando espaço em tempdb.

Você está usando o WinLink por acaso? Algo sobre isso parece vagamente familiar.

Meredith Poor
fonte
-4

Você deve ter um mecanismo de armazenamento em cache, como o memcached, para melhorar o desempenho


fonte
Mas isso não mudaria o uso da CPU no SQL Server, certo? Isso tornaria as consultas mais rápidas no site, e poderia haver problemas se algum item fosse alterado em uma tabela enquanto outra pessoa estivesse usando resultados em cache de memórias da mesma tabela, certo?
Levi Johansen
@ Levi, se você armazenar em cache os resultados da consulta em algum lugar na camada intermediária, as consultas não atingirão o banco de dados (exceto quando você precisar atualizar o cache).
Aaron Bertrand
11
Se a CPU também estiver alta quando ninguém estiver no site, então obviamente o armazenamento em cache de itens no nível da Web não ajudaria. Memcached é uma ótima ferramenta, mas não substitui uma pessoa competente para se sentar e descobrir o que o servidor está fazendo quando, supostamente, não deveria estar fazendo nada.
TomTom