0

以下は私の WHERE 句で、(特に 2 つの @subgroup 変数で) 繰り返しが含まれているため、コードを最適化するために何かできることはないかと考えていました。私のコードはそのままで問題なく動作しますが、もっときれいにできれば素晴らしいと思います。まずは簡単な説明。

asp ドロップダウンから入力する 5 つのパラメーターがあります。この質問の目的のために、私はそれらにデータを入力しました:

DECLARE
@DataCollection VARCHAR(50) = '2013/14 - Autumn 1 - Targets',
@StuYear VARCHAR(2) = '11',
@SubjectName VARCHAR(100) ='English',
@TeachingGroup VARCHAR(25) = 'Select All',
@SubGroup VARCHAR(15) = 'FSMYes',
@SubGroup2 VARCHAR(15) = 'SENS'

where ステートメントを使用すると、ドロップダウンの値に基づいて結果セットをフィルター処理できます。

@DataCollection、@StuYear、および @SubjectName はすべて必須であり、ドロップダウンにデフォルト値があります。残りはオプションです。

@subgroup の変数は、ドロップダウンでハードコーディングされた値に基づいて入力されるため、パラメーターが渡され、そのパラメーター値が WHERE 句の条件と一致する場合、特定の db 値がテーブルの特定の列にフィルター処理されます。

ここに私のSQLがあります:

WHERE
[StuYear] = @StuYear AND
[DataCollection] = @DataCollection AND
[Name] = @SubjectName AND (
    @TeachingGroup = 'Select All' OR 
    [TeachingGroup] = @TeachingGroup
) AND (
   @SubGroup = 'Select All' OR
   Gender = CASE --Gender
           WHEN @SubGroup = 'GenF' THEN 'F'
           WHEN @SubGroup = 'GenM' THEN 'M'
       END 
   OR
   LEFT(ks2av,1) = CASE --Attainer
           WHEN @SubGroup = 'High' THEN '5'
           WHEN @SubGroup = 'High' THEN '5'
           WHEN @SubGroup = 'Middle' THEN '4'
           WHEN @SubGroup = 'Low' THEN '3'
           WHEN @SubGroup = 'Low' THEN '2'
           WHEN @SubGroup = 'Low' THEN '1'
       END
   OR
   PupilPremium = CASE --Pupil Premium
           WHEN @Subgroup = 'PPYes' THEN 'Yes'
       END 
   OR
   FSM = CASE --Free School Meals
           WHEN @Subgroup = 'FSMYes' THEN 'Yes'
       END
   OR
   SEN = CASE --SEN
           WHEN @Subgroup = 'SENA' THEN 'A'
           WHEN @Subgroup = 'SENP' THEN 'P'
           WHEN @Subgroup = 'SENS' THEN 'S'
           WHEN @Subgroup = 'SENNo' THEN 'N'
       END
   OR
   (@SubGroup='SENYes' AND SEN IN ('A','P','S')) --SEN Yes
   OR
   EAL = CASE --English as an Additional Language
           WHEN @Subgroup = 'EALYes' THEN 'Yes'
       END
   OR
   LAC = CASE --Looked After Children
           WHEN @Subgroup = 'LACYes' THEN 'Yes'
       END
   OR --Gifted & Talented       
   GandT = CASE 
           WHEN @Subgroup = 'GandTYes' THEN 'Yes'
       END
   OR --Gifted Only       
   Gifted = CASE 
           WHEN @Subgroup = 'GiftedYes' THEN 'Yes'
       END
   OR --Talented Only       
   Talented = CASE 
           WHEN @Subgroup = 'TalentedYes' THEN 'Yes'
       END
)AND (
   @subgroup2 = 'Select All' OR
   Gender = CASE --Gender
           WHEN @subgroup2 = 'GenF' THEN 'F'
           WHEN @subgroup2 = 'GenM' THEN 'M'
       END 
   OR
   LEFT(ks2av,1) = CASE --Attainer
           WHEN @subgroup2 = 'High' THEN '5'
           WHEN @subgroup2 = 'High' THEN '5'
           WHEN @subgroup2 = 'Middle' THEN '4'
           WHEN @subgroup2 = 'Low' THEN '3'
           WHEN @subgroup2 = 'Low' THEN '2'
           WHEN @subgroup2 = 'Low' THEN '1'
       END
   OR
   PupilPremium = CASE --Pupil Premium
           WHEN @subgroup2 = 'PPYes' THEN 'Yes'
       END 
   OR
   FSM = CASE --Free School Meals
           WHEN @subgroup2 = 'FSMYes' THEN 'Yes'
       END
   OR
   SEN = CASE --SEN
           WHEN @subgroup2 = 'SENA' THEN 'A'
           WHEN @subgroup2 = 'SENP' THEN 'P'
           WHEN @subgroup2 = 'SENS' THEN 'S'
           WHEN @subgroup2 = 'SENNo' THEN 'N'
       END
   OR
   (@subgroup2='SENYes' AND SEN IN ('A','P','S')) --SEN Yes
   OR
   EAL = CASE --English as an Additional Language
           WHEN @subgroup2 = 'EALYes' THEN 'Yes'
       END
   OR
   LAC = CASE --Looked After Children
           WHEN @subgroup2 = 'LACYes' THEN 'Yes'
       END
   OR --Gifted & Talented       
   GandT = CASE 
           WHEN @subgroup2 = 'GandTYes' THEN 'Yes'
       END
   OR --Gifted Only       
   Gifted = CASE 
           WHEN @subgroup2 = 'GiftedYes' THEN 'Yes'
       END
   OR --Talented Only       
   Talented = CASE 
           WHEN @subgroup2 = 'TalentedYes' THEN 'Yes'
       END
)
4

1 に答える 1

2

これらの OR はすべて最適化が不十分になる傾向があります。これは、計画が 1 つのパスに対して選択され、あまり意味をなさない他のいくつかのパスで再利用されるためです。考慮できる 2 つのオプション:

  1. 動的 SQL。これにより、特定の各コード パスを個別にコンパイルおよび最適化できます。構成オプションを使用して、プラン キャッシュの肥大化を防ぐことができoptimize for ad hoc workloadsます。これにより、新しいプランが 2 回目に使用されるまで完全にキャッシュされなくなります。簡単な例:

    DECLARE @sql NVARCHAR(MAX) = N'SELECT ... 
      WHERE StuYear = @StuYear
        AND DataCollection = @DataCollection
        AND Name = @SubjectName';
    
    -- assuming optional parameters can't be NULL:
    IF @TeachingGroup <> 'Select All' THEN 
      SET @sql += N' AND TeachingGroup = @TeachingGroup';
    
    -- several more of these
    
    EXEC sp_executesql @sql,
      N'@StuYear VARCHAR(2), @DataCollection VARCHAR(50),
        @SubjectName VARCHAR(100), @TeachingGroup VARCHAR(25)',
      @StuYear, @DataCollection, @SubjectName, @TeachingGroup;
    
  2. クエリに追加OPTION (RECOMPILE)します。これらのバージョンのそれぞれが毎回コンパイルされるわけではないため、これは動的 SQL よりも全体的なコンパイルの点で少しコストがかかりますが、ここでの追加の利点は、パラメーターのスニッフィングを阻止できることです (異なるパラメーター値が動的 SQL の有効性に大幅に影響する可能性がある場合)。選ばれたプラン)。

余談ですが、こんな感じです。

SEN = CASE --SEN
       WHEN @Subgroup = 'SENA' THEN 'A'
       WHEN @Subgroup = 'SENP' THEN 'P'
       WHEN @Subgroup = 'SENS' THEN 'S'
       WHEN @Subgroup = 'SENNo' THEN 'N'
   END

次のように簡略化できます。

SEN = CASE WHEN @Subgroup LIKE 'SEN[APSN]%' THEN SUBSTRING(@Subgroup, 4, 1) END
于 2013-10-01T18:39:21.947 に答える