1

sp_executesqlいくつかのパラメーターで複雑な選択を渡すために使用しています。ストアド プロシージャから取り出して変数を宣言するよりも、この方法の方がはるかに時間がかかります。

SQL パラメーターのスニッフィングについて多くの質問を見てきましたが、私のシナリオはこれに当てはまるように思えます。ただしDBCC FREEPROCCACHE、外部の Select を呼び出したり修正したりした後Option (Recompile)でも、ストアド プロシージャの外部で同じクエリを記述する場合と比較して、別の非効率的な実行プランが使用されます。

ただし、引き続きストアド プロシージャを使用しますが、パラメーターのコピーをローカル変数として設定すると、効率的な実行プランが使用されます。

このシナリオでは、SQL パラメーターのスニッフィングが原因として除外されますか? クエリを再コンパイルするため、クエリが使用する既存の実行計画はありません。もしそうなら、この行動の他の理由として何が考えられるでしょうか?

SQLクエリのアイデアを以下に示します(エンティティフレームワークを介して生成された乱雑なもの)。これは高速なクエリですがsp_executesql、変数を取り出してパラメーターを入れてprocに入れると、非効率的な実行計画が生成されます

 DECLARE    @p__linq__0 INT = 2032
,@p__linq__1 UNIQUEIDENTIFIER = '8CC161FC-B8DE-4746-BA4F-62FA55DF26DE'
,@p__linq__2 uniqueidentifier= '8CC161FC-B8DE-4746-BA4F-62FA55DF26DE',
@p__linq__3 uniqueidentifier= '8CC161FC-B8DE-4746-BA4F-62FA55DF26DE',
@p__linq__4 uniqueidentifier= '8CC161FC-B8DE-4746-BA4F-62FA55DF26DE',
@p__linq__5 INT = 6771

SELECT 
[Limit1].[UserIdValue] AS [UserIdValue]
FROM   (SELECT [Extent1].[Id] AS [Id]
    FROM [dbo].[Request] AS [Extent1]
    WHERE ([Extent1].[InstanceId] = @p__linq__0) AND ([Extent1].[DeletedDate] IS NULL) AND (( EXISTS (SELECT 
        1 AS [C1]
        FROM ( SELECT 
            [Extent2].[TeamId] AS [TeamId], 
            [Extent2].[HasUpdateAccess] AS [HasUpdateAccess]
            FROM [dbo].[RequestTypeTeam] AS [Extent2]
            WHERE [Extent1].[RequestTypeId] = [Extent2].[RequestTypeId]
        )  AS [Project1]
        WHERE ([Project1].[HasUpdateAccess] = 1) AND ( EXISTS (SELECT 
            1 AS [C1]
            FROM [dbo].[UserTeam] AS [Extent3]
            WHERE ([Project1].[TeamId] = [Extent3].[TeamId]) AND ([Extent3].[UserId] = @p__linq__1)
        ))
    )) OR (([Extent1].[InsertUserId] = @p__linq__2) AND ( EXISTS (SELECT 
        1 AS [C1]
        FROM ( SELECT 
            [Extent4].[TeamId] AS [TeamId], 
            [Extent4].[HasCreatorAccess] AS [HasCreatorAccess]
            FROM [dbo].[RequestTypeTeam] AS [Extent4]
            WHERE [Extent1].[RequestTypeId] = [Extent4].[RequestTypeId]
        )  AS [Project4]
        WHERE ([Project4].[HasCreatorAccess] = 1) AND ( EXISTS (SELECT 
            1 AS [C1]
            FROM [dbo].[UserTeam] AS [Extent5]
            WHERE ([Project4].[TeamId] = [Extent5].[TeamId]) AND ([Extent5].[UserId] = @p__linq__3)
        ))
    ))) OR ( EXISTS (SELECT 
        1 AS [C1]
        FROM [dbo].[RequestTeam] AS [Extent6]
        WHERE ([Extent1].[Id] = [Extent6].[RequestId]) AND ([Extent6].[TeamId] IN (3147, 3165))
    )) OR ( EXISTS (SELECT 
        1 AS [C1]
        FROM ( SELECT 
            (SELECT 
                COUNT(1) AS [A1]
                FROM [dbo].[RequestControlData] AS [Extent8]
                WHERE ([Project8].[Id] = [Extent8].[ControlId]) AND ([Extent8].[RequestId] = [Extent1].[Id]) AND ([Extent8].[UserIdValue] = @p__linq__4)) AS [C1]
            FROM ( SELECT 
                [Extent7].[Id] AS [Id]
                FROM [dbo].[Control] AS [Extent7]
                WHERE ([Extent7].[RequestTypeId] IS NOT NULL) AND ([Extent1].[RequestTypeId] = [Extent7].[RequestTypeId]) AND ([Extent7].[DeletedDate] IS NULL) AND ([Extent7].[IsAuthorisation] = 1)
            )  AS [Project8]
        )  AS [Project9]
        WHERE [Project9].[C1] > 0
    ))) AND ( NOT ([Extent1].[StatusId] IN (1071))) AND ( NOT ([Extent1].[RequestTypeId] IN (1215)))) AS [Filter11] 
OUTER APPLY  (SELECT TOP (1) 
    [Extent9].[ControlId] AS [ControlId], 
    [Extent9].[UserIdValue] AS [UserIdValue], 
    [Extent10].[Id] AS [Id], 
    [Extent10].[SharedControlId] AS [SharedControlId]
    FROM  [dbo].[RequestControlData] AS [Extent9]
    INNER JOIN [dbo].[Control] AS [Extent10] ON [Extent9].[ControlId] = [Extent10].[Id]
    WHERE ([Filter11].[Id] = [Extent9].[RequestId]) AND (([Extent10].[SharedControlId] = @p__linq__5) OR (([Extent10].[SharedControlId] IS NULL) AND (@p__linq__5 IS NULL
    ))) 
    )
     AS [Limit1]  
4

2 に答える 2