Das von Ihnen beschriebene Verhalten ist häufig auf einen falsch zwischengespeicherten Abfrageplan und/oder veraltete Statistiken zurückzuführen.
Dies tritt häufig auf, wenn Sie eine große Anzahl von Parametern in einer WHERE-Klausel haben, insbesondere eine lange Liste von Parametern in der Form:
(@parameter1 is NULL OR TableColumn1 = @parameter1)
Angenommen, der zwischengespeicherte Abfrageplan läuft ab, und die Prozedur wird mit einem nicht repräsentativen Satz von Parametern aufgerufen. Der Plan wird dann für dieses Datenprofil zwischengespeichert. ABER, wenn der Prozess häufiger mit einem sehr unterschiedlichen Satz von Parametern auftritt, ist der Plan möglicherweise nicht angemessen. Dies wird oft als „Parameter-Sniffing“ bezeichnet.
Es gibt Möglichkeiten, dieses Problem zu mildern und zu beseitigen, aber sie können Kompromisse beinhalten und von Ihrer SQL Server-Version abhängen. Sehen Sie sich OPTIMIZE FOR
an
und OPTIMIZE FOR UNKNOWN
. WENN (und es ist ein großes Wenn) der Proc selten aufgerufen wird, aber so schnell wie möglich laufen muss, können Sie ihn als OPTION(RECOMPILE)
, um bei jedem Aufruf eine Neukompilierung zu erzwingen, ABER tun Sie dies nicht für häufig aufgerufene Prozesse ODER ohne Untersuchung.
[HINWEIS:Beachten Sie, welche Service Pack und kumulatives Update (CU) Ihre SQL Server 2008-Box hat, da die Neukompilierungs- und Parameter-Sniffing-Logik in einigen Versionen anders funktioniert]
Führen Sie diese Abfrage (von Glenn Berry) aus, um den Status der Statistiken zu ermitteln:
-- 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);