Eu armazenei um procedimento que atinge o tempo limite insanamente toda vez que é chamado do aplicativo da web.
Eu iniciei o Sql Profiler e rastreei as chamadas que expiraram e finalmente descobri estas coisas:
- Ao executar as instruções de dentro do MS SQL Management Studio, com os mesmos argumentos (na verdade, copiei a chamada de procedimento do rastreamento do perfil sql e executei): Termina em 5 ~ 6 segundos em média.
- Mas, quando chamado de um aplicativo da web, leva mais de 30 segundos (em rastreamento), então minha página da web atinge o tempo limite até lá.
Além do fato de que meu aplicativo web tem seu próprio usuário, tudo é igual (mesmo banco de dados, conexão, servidor etc), também tentei executar a consulta diretamente no estúdio com o usuário do aplicativo web e não leva mais de 6 seg.
Como faço para descobrir o que está acontecendo?
Estou assumindo que não tem nada a ver com o fato de usarmos camadas BLL> DAL ou adaptadores de tabela, pois o rastreamento mostra claramente que o atraso está no procedimento real. Isso é tudo em que consigo pensar.
EDIT Eu descobri neste link que o ADO.NET define ARITHABORT
como verdadeiro - o que é bom na maioria das vezes, mas às vezes isso acontece, e a solução sugerida é adicionar uma with recompile
opção ao procedimento armazenado. No meu caso, não está funcionando, mas suspeito que seja algo muito semelhante a isso. Alguém sabe o que mais o ADO.NET faz ou onde posso encontrar a especificação?
fonte
Respostas:
Já tive um problema semelhante no passado, por isso estou ansioso para ver uma solução para essa questão. O comentário de Aaron Bertrand sobre o OP levou ao tempo limite da Consulta quando executado da web, mas muito rápido quando executado do SSMS , e embora a pergunta não seja uma duplicata, a resposta pode muito bem se aplicar à sua situação.
Em essência, parece que o SQL Server pode ter um plano de execução em cache corrompido. Você está atingindo o plano ruim com o seu servidor web, mas o SSMS cai em um plano diferente, pois há uma configuração diferente no sinalizador ARITHABORT (que, de outra forma, não teria impacto em sua consulta / proc armazenado em particular).
Consulte ADO.NET chamando o procedimento armazenado T-SQL causa uma SqlTimeoutException para outro exemplo, com uma explicação e resolução mais completas.
fonte
DBCC DROPCLEANBUFFERS
eDBCC FREEPROCCACHE
resolvi! Estou supondo que o plano de execução foi de alguma forma corrompido ou não atualizado. Tenho dúvidas de que seja uma solução permanente, se pudesse ser corrompido uma vez, poderia corromper novamente. Portanto, ainda estou procurando as causas plausíveis. Como o aplicativo da web voltou a funcionar, não preciso sentir a pressão. Muito obrigado.OPTIMIZE FOR
ouOPTION(Recompile)
consultar dicas nas consultas que estão causando problemas. Este artigo discute o problema em detalhes. Se o Entity Framework estiver gerando suas consultas, esta postagem parece fornecer uma maneira de adicionar uma dica de consulta às suas consultas.Também percebi que as consultas estavam sendo executadas lentamente na web e rápidas no SSMS e, finalmente, descobri que o problema era algo chamado de detecção de parâmetro.
A correção para mim foi alterar todos os parâmetros usados no sproc para variáveis locais.
por exemplo. mudança:
para:
Parece estranho, mas resolveu meu problema.
fonte
Não para spam, mas como uma solução útil para outras pessoas, nosso sistema apresentou um alto grau de tempo limite.
Tentei configurar o procedimento armazenado para ser recompilado usando
sp_recompile
e isso resolveu o problema para um SP.No final das contas, havia um grande número de SPs que estavam expirando, muitos dos quais nunca tinham feito isso antes, usando
DBCC DROPCLEANBUFFERS
eDBBC FREEPROCCACHE
a taxa de incidentes de tempos limite caiu significativamente - ainda há ocorrências isoladas, algumas onde eu suspeito que a regeneração do plano está levando um tempo, e alguns onde os SPs estão genuinamente abaixo do desempenho e precisam ser reavaliados.fonte
DBCC DROPCLEANBUFFERS
eDBCC FREEPROCCACHE
não fez diferença.Será que alguma outra chamada de banco de dados feita antes de o aplicativo da web chamar o SP está mantendo uma transação aberta? Esse pode ser um motivo para este SP esperar quando chamado pelo aplicativo da web. Eu digo isolar a chamada no aplicativo da web (colocá-la em uma nova página) para garantir que alguma ação anterior no aplicativo da web esteja causando esse problema.
fonte
Simplesmente recompilar o procedimento armazenado (função de tabela no meu caso) funcionou para mim
fonte
como @Zane disse que pode ser devido à detecção de parâmetros. Eu experimentei o mesmo comportamento e dei uma olhada no plano de execução do procedimento e todas as declarações do sp em uma linha (copiei todas as declarações do procedimento, declarei os parâmetros como variáveis e atribuí os mesmos valores para a variável como os parâmetros tinham). No entanto, o plano de execução parecia completamente diferente. A execução do sp levou de 3 a 4 segundos e as instruções em uma linha com exatamente os mesmos valores foram retornadas instantaneamente.
Depois de pesquisar no Google, achei uma leitura interessante sobre esse comportamento: lento no aplicativo, rápido no SSMS?
O problema é que eu tinha parâmetros que podiam ser deixados nulos e, se fossem passados como nulos, seriam inicializados com um valor padrão.
Depois que mudei para
funcionou como um encanto novamente.
fonte