Den adfærd, du beskriver, skyldes ofte en forkert cachelagret forespørgselsplan og/eller forældede statistikker.
Det opstår ofte, når du har et stort antal parametre i en WHERE-sætning, især en lang liste over dem, der har formen:
(@parameter1 is NULL OR TableColumn1 = @parameter1)
Lad os sige, den cachelagrede forespørgselsplan udløber, og procen kaldes med et ikke-repræsentativt sæt parametre. Planen cachelagres derefter for denne dataprofil. MEN hvis proc’en oftere er almindelig med et meget andet sæt parametre, er planen måske ikke passende. Dette er ofte kendt som 'parameter sniffing'.
Der er måder at afbøde og eliminere dette problem, men de kan involvere afvejninger og afhænger af din SQL Server-version. Se på OPTIMIZE FOR
og OPTIMIZE FOR UNKNOWN
. HVIS (og det er et stort hvis) procen kaldes sjældent, men skal køre så hurtigt som muligt, kan du markere det som OPTION(RECOMPILE)
, for at tvinge en omkompilering hver gang den kaldes, MEN gør ikke dette for ofte kaldede procs ELLER uden undersøgelse.
[BEMÆRK:vær opmærksom på, hvilken Service pack og kumulativ opdatering (CU) din SQL Server 2008-boks har, da rekompilerings- og parametersniffingslogikken fungerer anderledes i nogle versioner]
Kør denne forespørgsel (fra Glenn Berry) for at bestemme statistikkens tilstand:
-- 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);