O comportamento que você está descrevendo geralmente se deve a um plano de consulta armazenado em cache incorretamente e/ou estatísticas desatualizadas.
Geralmente ocorre quando você tem um grande número de parâmetros em uma cláusula WHERE, especialmente uma longa lista daqueles que estão no formato:
(@parameter1 is NULL OR TableColumn1 = @parameter1)
Digamos, o plano de consulta em cache expira e o proc é chamado com um conjunto de parâmetros não representativo. O plano é então armazenado em cache para este perfil de dados. MAS, se o proc for mais comum com um conjunto de parâmetros muito diferente, o plano pode não ser apropriado. Isso é muitas vezes conhecido como 'sniffing de parâmetros'.
Existem maneiras de mitigar e eliminar esse problema, mas elas podem envolver compensações e depender da sua versão do SQL Server. Veja
OPTIMIZE FOR
e OPTIMIZE FOR UNKNOWN
. SE (e é um grande se) o proc é chamado com pouca frequência, mas deve ser executado o mais rápido possível, você pode marcá-lo como OPTION(RECOMPILE)
, para forçar uma recompilação cada vez que for chamado, MAS não faça isso para procs chamados com frequência OU sem investigação. [OBSERVAÇÃO:saiba que Service pack e atualização cumulativa (CU) sua caixa do SQL Server 2008 tem, pois a lógica de recompilação e sniffing de parâmetros funciona de maneira diferente em algumas versões]
Execute esta consulta (de Glenn Berry) para determinar o estado das estatísticas:
-- When were Statistics last updated on all indexes?
SELECT o.name, i.name AS [Index Name],
STATS_DATE(i.[object_id], i.index_id) AS [Statistics Date],
s.auto_created, s.no_recompute, s.user_created, st.row_count
FROM sys.objects AS o WITH (NOLOCK)
INNER JOIN sys.indexes AS i WITH (NOLOCK)
ON o.[object_id] = i.[object_id]
INNER JOIN sys.stats AS s WITH (NOLOCK)
ON i.[object_id] = s.[object_id]
AND i.index_id = s.stats_id
INNER JOIN sys.dm_db_partition_stats AS st WITH (NOLOCK)
ON o.[object_id] = st.[object_id]
AND i.[index_id] = st.[index_id]
WHERE o.[type] = 'U'
ORDER BY STATS_DATE(i.[object_id], i.index_id) ASC OPTION (RECOMPILE);