Il comportamento che descrivi è spesso dovuto a un piano di query memorizzato nella cache in modo errato e/o a statistiche non aggiornate.
Si verifica comunemente quando si dispone di un numero elevato di parametri in una clausola WHERE, in particolare un lungo elenco di quelli che hanno la forma:
(@parameter1 is NULL OR TableColumn1 = @parameter1)
Supponiamo che il piano di query memorizzato nella cache scada e il processo venga chiamato con un insieme di parametri non rappresentativo. Il piano viene quindi memorizzato nella cache per questo profilo dati. MA, se il proc è più spesso comune con un insieme di parametri molto diverso, il piano potrebbe non essere appropriato. Questo è spesso noto come "sniffing dei parametri".
Esistono modi per mitigare ed eliminare questo problema, ma possono comportare compromessi e dipendono dalla versione di SQL Server in uso. Guarda OPTIMIZE FOR
e OPTIMIZE FOR UNKNOWN
. SE (ed è un grande se) il proc viene chiamato raramente ma deve essere eseguito il più velocemente possibile, puoi contrassegnarlo come OPTION(RECOMPILE)
, per forzare una ricompilazione ogni volta che viene chiamato, MA non farlo per processi chiamati frequentemente O senza indagine.
[NOTA:tieni presente quale Service pack e aggiornamento cumulativo (CU) la tua casella di SQL Server 2008 ha, poiché la logica di ricompilazione e di sniffing dei parametri funziona in modo diverso in alcune versioni]
Esegui questa query (da Glenn Berry) per determinare lo stato delle statistiche:
-- 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);