(Pytanie przeniesione z SO)
Mam tabelę (dane fikcyjne) z indeksem klastrowym zawierającym 2 kolumny:
Teraz uruchamiam te dwa zapytania:
declare
@productid int =1 ,
@priceid int = 1
SELECT productid,
t.priceID
FROM Transactions AS t
WHERE (productID = @productid OR @productid IS NULL)
AND (priceid = @priceid OR @priceid IS NULL)
SELECT productid,
t.priceID
FROM Transactions AS t
WHERE (productID = @productid)
AND (priceid = @priceid)
Rzeczywisty plan wykonania obu zapytań to:
Jak widać, pierwszy korzysta ze SKANOWANIA, a drugi SZUKAJ.
Jednak - dodanie OPTION (RECOMPILE)
do pierwszego zapytania spowodowało, że plan wykonania również używał SEEK:
Przyjaciele na czacie DBA powiedzieli mi, że:
W zapytaniu @ productid = 1, co oznacza, że (productID = @ productID LUB @productID IS NULL) można uprościć (productID = @ productID). Pierwszy wymaga skanu do pracy z dowolną wartością @productID, drugi może użyć funkcji seek. Tak więc, gdy użyjesz RECOMPILE, SQL Server sprawdzi, jaką wartość faktycznie masz w @productID i przygotuje najlepszy plan. Przy wartości innej niż null w @productID wyszukiwanie jest najlepsze. Jeśli wartość @productID jest nieznana, plan musi pasować do każdej możliwej wartości w @productID, która wymagałaby skanowania. Uwaga: Opcja (RECOMPILE) wymusi rekompilację planu za każdym razem, gdy go uruchomisz, co doda kilka milisekund do każdego wykonania. Jest to jednak problem tylko wtedy, gdy zapytanie jest uruchamiane bardzo często.
Również :
Jeśli @productID ma wartość null, jakiej wartości byś szukał? Odpowiedź: nie ma czego szukać. Wszystkie wartości się kwalifikują.
Rozumiem, że OPTION (RECOMPILE)
zmusza program SQL Server do zobaczenia, jakie rzeczywiste wartości mają parametry, i do sprawdzenia, czy można go poszukać.
Ale teraz tracę korzyści z kompilacji z wyprzedzeniem.
Pytanie
IMHO - SKANOWANIE nastąpi tylko wtedy, gdy parametr jest pusty.
W porządku - pozwól, aby SQL SERVER stworzył plan wykonania dla SCAN.
ALE jeśli SQL Server widzi, że uruchamiam to zapytanie wiele razy z wartościami 1,1
, to dlaczego nie tworzy INNEGO planu wykonania i nie używa do tego SEEK?
AFAIK - SQL tworzy plan wykonania dla najbardziej trafionych zapytań .
Dlaczego SQL SERVER nie zapisuje planu wykonania dla:
@productid int =1 , @priceid int = 1
(Uruchamiam go wiele razy z tymi wartościami)
- Czy można zmusić SQL do zachowania tego planu wykonania (który używa SEEK) - do przyszłego wywołania?