2

この T-SQL コードを書き直して同じ結果を生成する方法

   SELECT   ACC.Title,
            ACC.AdvertiserHierarchyId,
            1 AS Counter
    FROM    admanAdvertiserHierarchy_tbl ACC
    JOIN    dbo.admanAdvertiserObjectType_tbl AOT ON AOT.AdvertiserObjectTypeId = ACC.AdvertiserObjectTypeId
              WHERE  (EXISTS
                         (SELECT 1
                          FROM    dbo.admanAdvertiserHierarchy_tbl CAMP
                          JOIN    dbo.admanAdvertiserAdGroup_tbl AG ON CAMP.AdvertiserHierarchyId = AG.AdvertiserHierarchyId
                          JOIN    dbo.admanAdvertiserCreative_tbl AC ON AC.AdvertiserAdGroupId = AG.AdvertiserAdGroupId
                          AND     CAMP.ParentAdvertiserHierarchyId = ACC.AdvertiserHierarchyId
                          WHERE   CAMP.ERROR = 0
                                  AND AC.Dirty & 7 > 0
                                  AND AC.ERROR = 0
                                  AND AG.ERROR = 0 ))

そのため、オプティマイザーがインデックスを効率的に使用できなくなります。次の結果を達成しようとしています

    Title                               AdvertiserHierarchyId       Counter
    trcom65@travelrepublic.co.uk        15908                       1
    paul570@travelrepublic.co.uk        37887                       1
    es88@travelrepublic.co.uk           37383                       1
    it004@travelrepublic.co.uk          27006                       1
    011                                 10526                       1
    013                                 10528                       1
    033                                 12013                       1
    062                                 17380                       1
    076                                 20505                       1

これはダーティな tinyint 列の数です

    Dirty   total
    0       36340607
    1       117569
    2       873553
    3       59

静的理由テーブルにリンクする

    DirtyReasonId   Title
    0               Nothing
    1               Overnight Engine
    2               End To End
    3               Overnight And End To End
    4               Pause Resume
    5               Overnight Engine and Paused
    6               Overnight Engine E2E and Paused
    7               All Three
4

1 に答える 1

3

BITWISE AND 演算子の使用について具体的に質問している場合は、あなたが正しいと思います。少なくとも、Dirty を先頭の列として持つインデックスでは、SQL Server がそれを sargable と見なす可能性は低いです。

使用中の最下位 2 ビット (Dirty の最大値は 3) のみを表示していますが、最下位 3 ビットをテストしています。

DirtyAC.Dirty > 0の最大値が 3 の場合、同等の結果が返されます。ただし、他の (上位) ビットが設定されている可能性があります。たとえば、Dirty が 8 に設定されている可能性があります。したがって、目的が下位 3 ビットのみをチェックすることである場合は、3 ビットのみをテストするようにする必要があります。最下位ビット。この式はそれを行い、述語の 1 つは検索可能です。

( AC.Dirty > 0 AND AC.Dirty % 8 > 0 )

これは基本的に、最初に ANY ビットAC.Dirtyが設定されているかどうかをテストし、次に最後の 3 つのビットのいずれかが設定されているかどうかをチェックします。(MODULO 除算演算子を使用して、AC.Dirty を 8 で割った余りを返します。これはもちろん、0 から 7 までの整数値を返します。0 を取得した場合、下位 3 ビットのいずれも含まれていないことがわかります。そうでなければ、ビットの少なくとも 1 つが設定されていることがわかります。

明確にするために、述語 onAC.Dirty > 0は冗長です。Dirtyデータベースが少なくとも既存のインデックスを先頭の列として使用することを検討できるようにしたい場合に備えて、ここに含まれています。


考慮すべき別のオプションとして、永続化された COMPUTED COLUMN を式に追加し、その上にインデックスを作成する方法があります。しかし、それはここで必要なものには少しやり過ぎのようです。


テーブル (AC) で使用されるインデックスを取得することについて具体的に質問している場合admanAdvertiserCreative_tbl、おそらく最良の候補は のインデックスをカバーするでしょう(AdvertiserAdGroupId, Error, Dirty)


以下の SQL リライトは同等の結果を返しますが、おそらくパフォーマンスが向上します (データの分布、インデックスなどによって異なります)。

基本的に、EXISTS (相関サブクエリ) をサブクエリへの JOIN に置き換えます。サブクエリは、サブクエリを関連付けるために参照した列である CAMP.ParentAdvertiserHierarchyId の個別の値を返します。

これは、使用可能なインデックスに応じて、インデックスを使用する場合と使用しない場合があります。(主キーにクラスター化された一意のインデックスがあり、外部キーにクラスター化されていないインデックスがある可能性が高いため、結合のパフォーマンスが向上するはずです。)

未テスト:

SELECT  ACC.Title,
        ACC.AdvertiserHierarchyId,
        1 AS Counter
FROM    admanAdvertiserHierarchy_tbl ACC
JOIN    dbo.admanAdvertiserObjectType_tbl AOT 
        ON AOT.AdvertiserObjectTypeId = ACC.AdvertiserObjectTypeId
JOIN   (SELECT    CAMP.ParentAdvertiserHierarchyId
          FROM    dbo.admanAdvertiserHierarchy_tbl CAMP
          JOIN    dbo.admanAdvertiserAdGroup_tbl AG 
            ON    CAMP.AdvertiserHierarchyId = AG.AdvertiserHierarchyId
          JOIN    dbo.admanAdvertiserCreative_tbl AC 
            ON    AC.AdvertiserAdGroupId = AG.AdvertiserAdGroupId
         WHERE    CAMP.ERROR = 0
           AND    ( AC.Dirty > 0 AND AC.Dirty % 8 > 0 )
           AND    AC.ERROR = 0
           AND    AG.ERROR = 0 )
         GROUP BY CAMP.ParentAdvertiserHierarchyId
       ) c
  ON c.ParentAdvertiserHierarchyId = ACC.AdvertiserHierarchyId
于 2012-06-27T15:57:07.237 に答える