Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Solucionando problemas de consultas de longa duração no MS SQL Server

Prefácio


Existe um sistema de informação que eu administro. O sistema é composto pelos seguintes componentes:

1. Banco de dados MS SQL Server
2. Aplicação de servidor
3. Aplicativos cliente

Esses sistemas de informação são instalados em vários objetos. O sistema de informação é usado ativamente 24 horas por dia por 2 a 20 usuários ao mesmo tempo em cada objeto. Portanto, você não pode realizar a manutenção de rotina de uma só vez. Portanto, tenho que «espalhar» a desfragmentação de índice do SQL Server ao longo do dia, em vez de desfragmentar todos os índices fragmentados necessários de uma só vez. Isso também se aplica a outras operações.



A propriedade de atualização automática de estatísticas é definida nas propriedades do banco de dados. Além disso, as estatísticas são atualizadas no índice desfragmentado.

Problema


Há cerca de um ano, encontrei o seguinte problema:

De vez em quando, todas as consultas estavam lentas. Notavelmente, o tempo de atraso foi aleatório. Aconteceu em todos os objetos em um dia aleatório. Além disso, quando comecei a analisar a frequência com que os atrasos ocorrem (usando o profiler), descobri que eles ocorrem todos os dias em um horário aleatório. Os usuários nem sempre prestam atenção neles, mas os consideram como o único atraso aleatório, e então o sistema funciona rapidamente novamente.

Resolvendo o problema


Eu revisei todas as consultas de execução lenta. O mais estranho era que todas as consultas estavam lentas em um momento aleatório, mesmo as mais simples, como puxar o último registro de uma tabela com vários milhares de linhas.

Além disso, realizei os seguintes passos:

1. Analisei os logs do MS SQL Server e do Windows Server, mas não consegui encontrar a causa dos atrasos.
2. Analisei índices (fragmentação, etc.), adicionei os que faltavam e removi os não utilizados.
3. Analisei as consultas – algumas foram melhoradas.
4. Analisei as tarefas no SQL Agent e não consegui associar as tarefas ao problema de atraso.
5. Analisei as tarefas no Agendador de Tarefas e não consegui associar as tarefas ao problema de atraso.
6. O Profiler mostrou os resultados, mas não a causa dos atrasos.
7. Realizei uma verificação de impasses – nenhum bloqueio longo foi revelado.

Como resultado, passei mais de 3 meses na busca malsucedida do motivo de consultas ocasionais lentas. No entanto, revelei um fato interessante - em vez do indicador de execução do Worker, o indicador de espera decorrida aumentou para todas as consultas. Este fato me deu a ideia de que algo está errado com os discos. Eu os verifiquei - estava tudo bem.

Solução


Para minha surpresa, revelei acidentalmente que, quando uma consulta era executada lentamente no aplicativo, ela era executada rapidamente no SSMS. Um artigo ajudou a resolver o problema (pelo menos sugeriu a ideia).

Um parágrafo do artigo:

Na prática, a opção SET mais importante é ARITHABORT, pois o valor padrão dessa opção é diferente para aplicativos e para SQL Server Management Studio. Isso explica por que você pode detectar uma consulta de execução lenta em seu aplicativo e obter uma boa velocidade executando-a no SSMS. O aplicativo usa um plano que foi criado para um conjunto de valores que difere dos valores corretos reais. Considerando que, se você executar a consulta no SSMS, é mais provável que o cache ainda não tenha um plano de execução para ARITHABORT ON e, portanto, o SQL Server criará um plano para seus valores atuais.

A diferença na execução foi devido ao parâmetro SET ARITHABORT. Para todas as consultas executadas no SSMS, esta opção está habilitada, e para consultas externas (de aplicativos) – desabilitada. Ele não pode ser ativado nem mesmo por uma simples consulta de aplicativos:
SET ARITHABORT ON;

Seguiu-se uma ideia maluca – limpar o cache processual no momento de desligar.

Para a verificação manual subsequente, preciso escrever a seguinte instrução antes da consulta no SSMS:
SET ARITHABORT OFF;

Assim vamos simular o funcionamento da aplicação. Quando a consulta estava em execução há muito tempo, limpei o cache procedural. E isso sempre ajudou. Antes de limpar o cache procedural, a consulta pode ser executada de 20 a 30 segundos e, posteriormente, de 0 segundos.

Depois disso, realizei outro experimento – limpando todo o cache procedural de todo o banco de dados a cada hora via SQL Agent:
--cleaning the cache by database id
DBCC FLUSHPROCINDB (@db_id);

Depois disso, todas as consultas foram executadas muito rapidamente (menos de 0,05 segundos). Houve apenas algumas ocorrências de até 5-10 segundos de execução, mas os usuários não notaram nenhum travamento. Além disso, atualizar as estatísticas não melhorou os resultados, então desativei a atualização das estatísticas.

Após mais alguns meses de estudo, descobri que interrupções ocasionais ocorrem quando o cache consome tudo no servidor e não há espaço livre ou há memória livre, mas menos de 1 GB de RAM ou o serviço MS SQL Server ocupa toda a RAM alocada (via Gerenciador de Tarefas). Mas o segundo evento ocorreu apenas duas vezes por todo o estudo.

O fato é que literalmente tudo é escrito no cache, enquanto o cache nem sempre é liberado a tempo. O problema com o cache foi resolvido usando o programa EmptyStandbyList.exe.

Configurei este aplicativo via Agendador de Tarefas para executar 1 vez a cada hora. Depois de todo o trabalho realizado, não há interrupções de consulta em todos os objetos há mais de meio ano.

A única coisa que permanece incerta são os raros casos em que uma consulta é interrompida por 5 a 10 segundos uma vez por mês em um dia aleatório e em um horário aleatório. Houve 4 desses casos e apenas em dois objetos por meio ano, quando o serviço MS SQL Server ocupa toda a memória alocada por um curto período de tempo.

Basicamente, não há necessidade de se aprofundar, pois os usuários não percebem nenhum travamento e tudo funciona bem, mas se alguém tiver alguma opinião, ficarei grato por compartilhar.

Este artigo foi escrito para ajudar aqueles que se deparam com esses problemas, pois não encontrei uma resposta abrangente na Internet e passei muito tempo estudando o problema e encontrando a solução.

Veja também:

  1. Implementação do indicador de desempenho do SQL Server para consultas, procedimentos armazenados e gatilhos
  2. Automatizando a desfragmentação de índice no banco de dados MS SQL Server



Ferramenta útil:


dbForge Query Builder for SQL Server – permite que os usuários criem consultas SQL complexas de maneira rápida e fácil por meio de uma interface visual intuitiva sem escrita manual de código.