私の意見では、非常に奇妙な問題があります。次の方法でUDFを呼び出すと:
DECLARE @contact_id uniqueidentifier
DECLARE @group_id uniqueidentifier
SET @group_id = 'EE57E2AD-204B-4078-AFA4-11FA8375C2FD'
set @contact_id = 'E6EFCC9F-9D1C-4C38-A950-C45372F2A6D2'
SELECT COUNT( ID ) AS [CountAll]
FROM [Document] As [Document]
WHERE ([Document].[ID] IN (SELECT ID FROM [fs_Document_View_ee57e2ad_204b_4078_afa4_11fa8375c2fd](@contact_id, @group_id)))
4 秒間実行され、次の実行計画が得られます 。
次のようにハードコードされたパラメーターを使用してUDFを呼び出すと、次のようになります。
SELECT COUNT( ID ) AS [CountAll]
FROM [Document] As [Document]
WHERE ([Document].[ID] IN (SELECT ID FROM [fs_Document_View_ee57e2ad_204b_4078_afa4_11fa8375c2fd]('E6EFCC9F-9D1C-4C38-A950-C45372F2A6D2', 'EE57E2AD-204B-4078-AFA4-11FA8375C2FD')))
この実行計画を取得します。遅く、91 秒かかります。
なぜこれが起こっているのか誰にも説明できますか?
この関数は、同じパラメーターを渡して他の 4 つのネストされた関数を呼び出します。アイテムの表示権限に関連しています。
事前に助けてくれてありがとう。
アップデート
Ivan G. が言及したこの記事のオプション 2 を使用しました。
問題はパラメータ スニッフィングであり、オプション 2 で問題が解決されました。
パラメータ スニッフィングの問題を解決する別の方法は、パラメータ スニッフィングを無効にすることです。これは、スイッチまたはデータベース オプションでは実行できませんが、ストアド プロシージャ コードのスクリプト内から実行できます。>ストアド プロシージャを作成して、パラメーター スニッフィングを無効にする方法の例を次に示します。
DROP PROC [dbo].[DisplayBillingInfo]
GO
CREATE PROC [dbo].[DisplayBillingInfo]
@BeginDate DATETIME,
@EndDate DATETIME
WITH RECOMPILE
AS
DECLARE @StartDate DATETIME;
DECLARE @StopDate DATETIME;
SET @StartDate = @BeginDate;
SET @StopDate = @EndDate;
SELECT BillingDate, BillingAmt
FROM BillingInfo
WHERE BillingDate between @StartDate AND @StopDate;
パラメータ スニッフィングを無効にするために行ったのは、ストアド プロシージャ内でのパラメータ値の使用方法を変更することだけでした。プロシージャ内に 2 つの異なるローカル変数 (@StartDate と @EndDate) を作成し、これらの変数を渡されたパラメーターに設定してから、BETWEEN 条件でローカル変数を使用することで、パラメーター スニッフィングを無効にすることができました。オプティマイザーは実際の SELECT ステートメントでパラメーターの値を識別できないため、パラメーター スニッフィングは無効になっています。SQL Server は、ストアド プロシージャの呼び出しに使用されたパラメーター値を特定できないため、オプティマイザーは統計に基づいて一般的なプランを作成します。
上記のコードを使用してストアド プロシージャを実行すると、狭い範囲の日付または 1 年分の日付を使用して、コンパイルされた実行プランは常に "インデックス スキャン" 操作を実行します。パラメータ sniff がオフになっていることがわかります。これは、日付の範囲が短いと、通常はインデックス シーク操作が作成されることがわかっているためです。