パラメーター化されたクエリからパラメーター化されていないクエリに変更したときの、SQL Server でのステートメントの推定クエリ プランの動作を理解するのに苦労しています。
次のクエリがあります。
DECLARE @p0 UniqueIdentifier = '1fc66e37-6eaf-4032-b374-e7b60fbd25ea'
SELECT [t5].[value2] AS [Date], [t5].[value] AS [New]
FROM (
SELECT COUNT(*) AS [value], [t4].[value] AS [value2]
FROM (
SELECT CONVERT(DATE, [t3].[ServerTime]) AS [value]
FROM (
SELECT [t0].[CookieID]
FROM [dbo].[Usage] AS [t0]
WHERE ([t0].[CookieID] IS NOT NULL) AND ([t0].[ProductID] = @p0)
GROUP BY [t0].[CookieID]
) AS [t1]
OUTER APPLY (
SELECT TOP (1) [t2].[ServerTime]
FROM [dbo].[Usage] AS [t2]
WHERE ((([t1].[CookieID] IS NULL) AND ([t2].[CookieID] IS NULL))
OR (([t1].[CookieID] IS NOT NULL) AND ([t2].[CookieID] IS NOT NULL)
AND ([t1].[CookieID] = [t2].[CookieID])))
AND ([t2].[CookieID] IS NOT NULL)
AND ([t2].[ProductID] = @p0)
ORDER BY [t2].[ServerTime]
) AS [t3]
) AS [t4]
GROUP BY [t4].[value]
) AS [t5]
ORDER BY [t5].[value2]
このクエリは、Linq2SQL 式によって生成され、LINQPad から抽出されます。これにより、(私が知る限り)適切なクエリ プランが生成され、データベース上で約 10 秒で実行されます。ただし、パラメーターの 2 つの使用を正確な値に置き換えると、つまり、2 つの '= @p0' 部分を '= '1fc66e37-6eaf-4032-b374-e7b60fbd25ea' に置き換えます。クエリの実行時間が大幅に長くなりました (60 秒以上、まだ確認していません)。
一見無害に見える置換を実行すると、クエリ プランと実行の効率が大幅に低下するのはなぜでしょうか? 'DBCC FreeProcCache' でプロシージャ キャッシュをクリアして、不適切なプランをキャッシュしていないことを確認しましたが、動作は残ります。
私の本当の問題は、10 秒の実行時間 (少なくともしばらくの間) には耐えられますが、60 秒以上の実行時間には耐えられないことです。私のクエリは(上記のように)Linq2SQLによって生成されるため、データベースで次のように実行されます
exec sp_executesql N'
...
WHERE ([t0].[CookieID] IS NOT NULL) AND ([t0].[ProductID] = @p0)
...
AND ([t2].[ProductID] = @p0)
...
',N'@p0 uniqueidentifier',@p0='1FC66E37-6EAF-4032-B374-E7B60FBD25EA'
これは同じように実行時間が長くなります(これは、パラメーター化されたクエリを使用しているように見えるため、二重に奇妙だと思います.
どのインデックスを作成するかなどについてアドバイスを求めているわけではありません。一見似ているように見える3つのクエリでクエリプランと実行がなぜそれほど異なるのかを理解しようとしているだけです。
編集:パラメータ化されていないクエリとパラメータ化されたクエリの実行計画、および別の GUID を使用してパラメータ化されたクエリの実行計画 ( Heinzが提案) をアップロードしました。
それが私を助けるのに役立つことを願っています:)