Beteendet du beskriver beror ofta på en felaktigt cachad frågeplan och/eller inaktuell statistik.
Det uppstår vanligtvis när du har ett stort antal parametrar i en WHERE-sats, särskilt en lång lista med de som har formen:
(@parameter1 is NULL OR TableColumn1 = @parameter1)
Säg, den cachade frågeplanen löper ut och proc anropas med en icke-representativ uppsättning parametrar. Planen cachelagras sedan för denna dataprofil. MEN om proc är vanligare med en helt annan uppsättning parametrar, kanske planen inte är lämplig. Detta är ofta känt som "parametersniffning".
Det finns sätt att lindra och eliminera detta problem, men de kan innebära avvägningar och beror på din SQL Server-version. Titta på OPTIMIZE FOR
och OPTIMIZE FOR UNKNOWN
. OM (och det är ett stort om) procen anropas sällan men måste köras så snabbt som möjligt kan du markera det som OPTION(RECOMPILE)
, för att tvinga fram en omkompilering varje gång den anropas, MEN gör inte detta för ofta anropade processer ELLER utan utredning.
[OBS:var medveten om vilken Service pack och kumulativ uppdatering (CU) din SQL Server 2008-box har, eftersom omkompilerings- och parametersniffningslogiken fungerar annorlunda i vissa versioner]
Kör den här frågan (från Glenn Berry) för att fastställa statistikens tillstånd:
-- 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);