Поведението, което описвате, често се дължи на неправилно кеширан план на заявка и/или неактуална статистика.
Това обикновено се случва, когато имате голям брой параметри в клауза WHERE, особено дълъг списък от тези, които са във формата:
(@parameter1 is NULL OR TableColumn1 = @parameter1)
Да кажем, че кешираният план за заявка изтича и процедурата се извиква с непредставителен набор от параметри. След това планът се кешира за този профил на данни. НО, ако процедурата е по-често срещана с много различен набор от параметри, планът може да не е подходящ. Това често е известно като „намеряване на параметри“.
Има начини за смекчаване и премахване на този проблем, но те може да включват компромиси и зависят от вашата версия на SQL Server. Вижте OPTIMIZE FOR
и OPTIMIZE FOR UNKNOWN
. АКО (и това е голямо ако) процедурата се извиква рядко, но трябва да работи възможно най-бързо, можете да я маркирате като OPTION(RECOMPILE)
, за принудително прекомпилиране при всяко извикване, НО не правете това за често извиквани процедури ИЛИ без разследване.
[ЗАБЕЛЕЖКА:имайте предвид кой Сервизен пакет и кумулативна актуализация (CU) вашата кутия SQL Server 2008 има, тъй като логиката за прекомпилиране и надушване на параметри работи по различен начин в някои версии]
Изпълнете тази заявка (от Glenn Berry), за да определите състоянието на статистиката:
-- 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);