fundo
Eu tenho uma consulta em execução no SQL Server 2008 R2 que une e / ou une à esquerda cerca de 12 "tabelas" diferentes. O banco de dados é bastante grande, com muitas tabelas com mais de 50 milhões de linhas e cerca de 300 tabelas diferentes. É para uma empresa de grande porte que possui 10 armazéns em todo o país. Todos os armazéns lêem e gravam no banco de dados. Então é bem grande e muito ocupado.
A consulta com a qual estou tendo problemas é mais ou menos assim:
select t1.something, t2.something, etc.
from Table1 t1
inner join Table2 t2 on t1.id = t2.t1id
left outer join (select * from table 3) t3 on t3.t1id = t1.t1id
[etc]...
where t1.something = 123
Observe que uma das junções está em uma subconsulta não correlacionada.
O problema é que, a partir desta manhã, sem alterações (que eu ou qualquer pessoa da minha equipe conheça) no sistema, a consulta que normalmente leva cerca de 2 minutos para ser executada começa a demorar uma hora e meia para ser executada - quando correu de todo. O restante do banco de dados está funcionando bem. Tirei essa consulta do sproc em que ela normalmente é executada e em SSMS com variáveis de parâmetro codificadas com a mesma lentidão.
A estranheza é que, quando pego a subconsulta não correlacionada e a jogo em uma tabela temporária, e depois a uso em vez da subconsulta, a consulta é executada corretamente. Além disso (e isso é o mais estranho para mim) se eu adicionar esse pedaço de código ao final da consulta, a consulta será ótima:
and t.name like '%'
Concluí (talvez incorretamente) dessas pequenas experiências que o motivo da desaceleração se deve à forma como o plano de execução em cache do SQL é configurado - quando a consulta é um pouco diferente, ela precisa criar um novo plano de execução.
Minha pergunta é a seguinte: quando uma consulta que costumava ser executada rapidamente repentinamente começa a ser executada lentamente no meio da noite e nada mais é afetado, exceto por essa consulta, como solucioná-lo e evitá-lo no futuro ? Como sei o que o SQL está fazendo internamente para torná-lo tão lento (se a consulta incorreta for executada, posso obter seu plano de execução, mas ele não será executado - talvez o plano de execução esperado me daria alguma coisa?)? Se esse problema ocorrer no plano de execução, como evito que o SQL pense que planos de execução realmente ruins são uma boa idéia?
Além disso, isso não é um problema com a detecção de parâmetros. Já vi isso antes, e não é isso, pois mesmo quando codifico as variáveis no SSMS, ainda tenho desempenho lento.
Respostas:
Você pode começar verificando se o plano de execução ainda está no cache. Verifique
sys.dm_exec_query_stats
,sys.dm_exec_procedure_stats
esys.dm_exec_cached_plans
. Se o plano de execução incorreto ainda estiver armazenado em cache, você poderá analisá-lo e também verificar as estatísticas de execução. As estatísticas de execução conterão informações como leituras lógicas, tempo de CPU e tempo de execução. Isso pode dar fortes indicações de qual é o problema (por exemplo, varredura grande x bloqueio). Veja Identificar consultas problemáticas para uma explicação de como interpretar os dados.Não estou convencido. As variáveis codificadas no SSMS não provam que o plano de execução incorreta passado não foi compilado em uma entrada distorcida. Leia Sniffing de parâmetros, incorporação e as opções RECOMPILE para obter um artigo muito bom sobre o assunto. Lento no aplicativo, rápido no SSMS? Compreender os mistérios do desempenho é outra excelente referência.
Isso pode ser facilmente testado.
SET STATISTICS TIME ON
mostrará o tempo de compilação versus execução. SQL Server: Os contadores de desempenho de estatísticas também revelam se a compilação é um problema (francamente, acho improvável).No entanto, há algo semelhante que você pode acessar: o portão de concessão de consultas. Leia Entendendo a concessão de memória do servidor SQL para obter detalhes. Se sua consulta solicitar uma grande concessão no momento, não há memória disponível, ela terá que esperar e tudo parecerá como 'execução lenta' para o aplicativo. A análise das estatísticas das informações de espera revelará se esse é o caso.
Para uma discussão mais geral sobre o que medir e o que procurar, consulte Como analisar o desempenho do SQL Server
fonte
Esse é um problema da execução de consultas complexas no SQL Server. Felizmente, isso não acontece com tanta frequência.
Veja o plano de consulta para a consulta (quando ela estiver lenta). Suponho que você encontrará uma associação de loop aninhada ocorrendo uma ou mais vezes em tabelas sem índices para a associação. Isso realmente atrasa as coisas. Para avançar rapidamente, a maneira de corrigir isso é com uma dica. Adicione o seguinte no final da consulta:
Isso geralmente corrigiu esse problema para mim no passado.
O que pode estar acontecendo é que alterações sutis na tabela (ou na disponibilidade de espaço temporário) fazem com que a otimização do SQL prefira um algoritmo de junção mais lento. Isso pode ser bastante sutil e repentino. Quando você cria uma tabela temporária, o otimizador tem mais informações sobre a tabela (como seu tamanho), para gerar um plano melhor.
fonte
Geralmente, é um índice ausente que causa esse tipo de problema.
O que eu costumo fazer é executar a consulta usando o SQL Management Studio e ativar 'Incluir plano de execução real (CTRL + M)' e descobrir qual junção está apresentando a maior porcentagem.
O aplicativo não se concentra no gargalo, mas você pode encontrá-lo "rapidamente" apenas olhando para o resultado.
exemplo aqui:
fonte
Recentemente, experimentei esse mesmo problema que me levou a esta página.
@MartinSmith estava envolvido em algo quando recomendou atualizar suas estatísticas e explicar o plano. Gostaria de acrescentar que você também deve tentar garantir a execução de trabalhos / consultas que podem criar bloqueios e, assim, diminuir o tempo de resposta.
No meu caso, o culpado foi o trabalho de reunir estatísticas da tabela. Por alguma razão, ele não foi concluído na janela que deveria ter e continuou sendo executado quando os usuários foram reiniciados. Eu encontrei o processo, o matei e as consultas começaram a responder novamente.
Espero que isto ajude alguém
fonte
Você também precisa verificar se alguma tarefa de backup do servidor ou de Arquivamento \ indexação está em execução quando ocorrer um problema de desempenho no T-SQL \ Procedure.
fonte