Hoje, tive um problema com o tempo limite de um procedimento armazenado (demorou mais de 30 segundos) quando foi executado em uma página da Web ASP.NET, mas foi executado rapidamente quando executado no SSMS (demorou 5 segundos).
Depois de suspeitar que o culpado era o sniffing de parâmetros, mascarei os parâmetros de entrada e a consulta foi executada mais rapidamente.
Minha pergunta é: por que isso aconteceu?
Este sistema está em produção há mais de 5 anos, e esta é a primeira vez que vimos algo assim em nossos procedimentos armazenados. Isso é "desgaste do banco de dados"?
Resolvemos o problema, então não é grande coisa, mas estou curioso para saber por que isso estava acontecendo.
Basicamente, o que acontece é que, quando o SQL Server vê uma consulta que precisa compilar, ele usa os parâmetros chamados pela primeira vez para gerar o plano de execução. Isso pode ou não ser uma coisa boa, mas é o que acontece.
Por exemplo, digamos que você tenha uma mesa de frutas (100 linhas). Existem 98 linhas que são Maçã e apenas 2 linhas que contêm a fruta Laranja. Se você consultar essa tabela para a Apple, o plano provavelmente será compilado com um Scan. Isso é bom, pois é otimizado para essa consulta da Apple. Mas então, quando você deseja consultar o Orange, esse Scan é ineficiente. Mas é o plano armazenado que está sendo usado.
O fato é que isso acontece. Isso acontece o tempo todo. Normalmente não é um problema pendente, mas em alguns casos pode ser um problema muito grande. Uma solução para um problema contínuo de detecção de parâmetro inválido é que você pode utilizar a
OPTIMIZE FOR
dica de consulta para forçar o SQL Server a usar determinados valores de parâmetro ao gerar o plano de execução na compilação inicial.Um tanto irritantemente, o padrão do SSMS é para
SET ARITHABORT ON
enquanto a maioria das bibliotecas de clientes (ADO .Net, ODBC, OLE DB) especificamSET ARITHABORT OFF
. Provavelmente você tinha um plano "ir mal", mas quando tentou replicar via SSMS, a diferença no ARITHABORT resultou no uso de um plano diferente, que era "bom".Lento no Aplicativo, Rápido no SSMS? é uma grande referência para isso.
Provavelmente, uma recompilação foi acionada e, infelizmente, um conjunto atípico de entradas foi usado para a compilação.