Pergunta

Esta é uma pergunta que fiz em outro fórum que recebeu algumas respostas decentes, mas queria ver se alguém aqui tem mais informações.

O problema é que uma de suas páginas em um aplicativo da Web atinge o tempo limite quando chega a uma chamada de procedimento armazenado, então você usa o Sql Profiler ou os logs de rastreamento do aplicativo para localizar a consulta e colá-la no Management Studio para descobrir é por isso que está lento.Mas você o executa a partir daí e ele simplesmente segue em frente, retornando em menos de um segundo de cada vez.

Meu caso específico foi usar ASP.NET 2.0 e Sql Server 2005, mas acho que o problema poderia se aplicar a qualquer sistema RDBMS.

Foi útil?

Solução

Isso é o que aprendi até agora com minha pesquisa.

O .NET envia configurações de conexão que não são as mesmas que você obtém ao fazer login no Management Studio.Aqui está o que você verá se detectar a conexão com o Sql Profiler:

-- network protocol: TCP/IP  
set quoted_identifier off  
set arithabort off  
set numeric_roundabort off  
set ansi_warnings on  
set ansi_padding on  
set ansi_nulls off  
set concat_null_yields_null on  
set cursor_close_on_commit off  
set implicit_transactions off  
set language us_english  
set dateformat mdy  
set datefirst 7  
set transaction isolation level read committed  

Agora estou colando essas configurações acima de cada consulta que executo quando estou logado no SQL Server, para garantir que as configurações sejam as mesmas.

Para este caso, tentei cada configuração individualmente, após desconectar e reconectar, e descobri que alterar o arithabort de desligado para ligado reduziu a consulta do problema de 90 segundos para 1 segundo.

A explicação mais provável está relacionada à detecção de parâmetros, que é uma técnica que o Sql Server usa para escolher o que considera ser o plano de consulta mais eficaz.Quando você altera uma das configurações de conexão, o otimizador de consulta pode escolher um plano diferente e, nesse caso, aparentemente escolheu um plano ruim.

Mas não estou totalmente convencido disso.Tentei comparar os planos de consulta reais depois de alterar essa configuração e ainda não vi a diferença mostrar nenhuma alteração.

Há algo mais na configuração arithabort que pode fazer com que uma consulta seja executada lentamente em alguns casos?

A solução parecia simples:Basta colocar set arithabort no topo do procedimento armazenado.Mas isso pode levar ao problema oposto:altere os parâmetros de consulta e de repente ele roda mais rápido com 'off' do que 'on'.

Por enquanto, estou executando o procedimento 'com recompilação' para garantir que o plano seja regenerado todas as vezes.Está tudo bem para este relatório específico, pois leva talvez um segundo para recompilar, e isso não é muito perceptível em um relatório que leva de 1 a 10 segundos para retornar (é um monstro).

Mas não é uma opção para outras consultas que são executadas com muito mais frequência e precisam retornar o mais rápido possível, em apenas alguns milissegundos.

Outras dicas

Eu tive problemas semelhantes.Tente definir a opção "WITH RECOMPILE" no sproc create para forçar o sistema a recalcular o plano de execução cada vez que ele for chamado.Às vezes, o processador de consulta fica confuso em procedimentos armazenados complexos com muitas ramificações ou instruções de caso e apenas extrai um plano de execução realmente abaixo do ideal.Se isso parecer "resolver" o problema, você provavelmente precisará verificar se as estatísticas estão atualizadas e/ou analisar o sproc.

Você também pode confirmar isso traçando o perfil do sproc.Quando você o executa no SQL Managment Studio, como o IO se compara ao seu perfil no aplicativo ASP.NET.Se forem muitos, isso apenas reforça que está executando um plano de execução ruim.

Você já ativou o rastreamento do ASP.NET?Tive um caso em que o problema não era o procedimento armazenado SQL em si, mas o fato de o procedimento retornar 5.000 linhas e o aplicativo estar tentando criar ListItems vinculados a dados com esses 5.000 itens que estava causando o problema.

Você também pode examinar os tempos de execução entre as funções do aplicativo da web por meio do rastreamento para ajudar a rastrear as coisas.

teste isso primeiro em uma caixa de teste, altere-o em um nível de servidor para sql server

declare @option int

Definir @Option = @@ Opções | 64

EXEC SP_CONFIGURE 'Opções do usuário', @Option

RECONFIGURAR

O mesmo problema que tive com os serviços de relatórios SQL.Tente verificar o tipo de variáveis, eu estava enviando diferentes tipos de variável para o SQL, como o envio do Varchar no lugar onde deveria ser inteiro ou algo assim.Depois de sincronizar os tipos de variáveis ​​no Reporting Service e no procedimento armazenado no SQL, resolvi o problema.

Você poderia tentar usar o comando sp_who2 para ver o que o processo em questão está fazendo.Isso mostrará se ele está bloqueado por outro processo ou se está consumindo uma quantidade excessiva de CPU e/ou tempo de io.

Tivemos o mesmo problema e aqui está o que descobrimos.

o tamanho do log do nosso banco de dados estava sendo mantido no padrão (814 MB) e o crescimento automático era de 10%.No servidor, a memória máxima do servidor também foi mantida na configuração padrão (2147483647 MB).

Quando nosso log ficou cheio e precisou crescer, ele usou toda a memória do servidor e não sobrou nada para o código ser executado, então o tempo limite expirou.O que acabamos fazendo foi definir o tamanho inicial do arquivo de log do banco de dados para 1 MB e a memória máxima do servidor para 2.048 MB.Isso resolveu instantaneamente nosso problema.Claro, você pode alterar essas duas propriedades para atender às suas necessidades, mas esta é uma ideia para alguém que está enfrentando o problema de tempo limite ao executar um procedimento armazenado via código, mas ele é executado super rápido no SSMS e as soluções acima não ajudam.

Tente alterar o valor do tempo limite do SelectCommand:

DataAdapter.SelectCommand.CommandTimeout = 120;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top