2011-04-21 5 views
1

これはストアドプロシージャ内にあります。これはif文です。 @AsOfDateは、の日付データ型に渡されます。私が持っている質問はなぜ最も内側に存在するものを削除してより良いパフォーマンスを得るのですか?文全体がIF EXISTSにあるときのみですか?内部存在チェックでIF EXISTSを使用すると疑わしいパフォーマンスが発生する

二つのテーブル:

  • dbo.TXXX_InventoryDe​​tail - 日までの13億records..stats
  • dbo.TXXX_InventoryFull - 日までの980万records..stats

声明:io出力

if exists (select 1 
      from dbo.TXXX_InventoryDetail o 
      where exists (select 1 
          from dbo.TXXX_InventoryFull i 
          where i.C001_AsOfDate= o.C001_AsOfDate 
          and i.C001_ProductID=o.C001_ProductID 
          and i.C001_StoreNumber=o.C001_StoreNumber 
          and [email protected] 
          and (i.C001_LastModelDate!=o.C001_LastModelDate 
            or o.C001_InventoryQty!=o.C001_InventoryQty 
            or i.C001_OnOrderQty!=o.C001_OnOrderQty 
            or i.C001_TBOQty!=o.C001_TBOQty 
            or i.C001_ModelQty!=o.C001_ModelQty 
            or i.C001_TBOAdjustQty!=o.C001_TBOAdjustQty 
            or i.C001_ReturnQtyPending!=o.C001_ReturnQtyPending 
            or i.C001_ReturnQtyInProcess!=o.C001_ReturnQtyInProcess 
            or i.C001_ReturnQtyDueOut!=o.C001_ReturnQtyDueOut)) 
       and [email protected]) 

  • テーブル 'TXXX_InventoryFull'。スキャンカウント9240262、論理読み取り29548864
  • テーブル 'T001_InventoryDe​​tail'。スキャン回数1は、論理的には、私は存在する二を削除して行う場合は17259

を読み込み参加:

if exists (select 1 
      from dbo.TXXX_InventoryDetail o, 
        dbo.TXXX_InventoryFull i 
      where i.C001_AsOfDate= o.C001_AsOfDate 
          and i.C001_ProductID=o.C001_ProductID 
          and i.C001_StoreNumber=o.C001_StoreNumber 
          and [email protected] 
          and (i.C001_LastModelDate!=o.C001_LastModelDate 
            or o.C001_InventoryQty!=o.C001_InventoryQty 
            or i.C001_OnOrderQty!=o.C001_OnOrderQty 
            or i.C001_TBOQty!=o.C001_TBOQty 
            or i.C001_ModelQty!=o.C001_ModelQty 
            or i.C001_TBOAdjustQty!=o.C001_TBOAdjustQty 
            or i.C001_ReturnQtyPending!=o.C001_ReturnQtyPending 
            or i.C001_ReturnQtyInProcess!=o.C001_ReturnQtyInProcess 
            or i.C001_ReturnQtyDueOut!=o.C001_ReturnQtyDueOut) 
       and [email protected]) 

IO出力:

  • テーブル 'TXXX_InventoryDe​​tail'。スキャンカウント0、論理読み取り333952
  • テーブル 'TXXX_InventoryFull'。スキャン数1、論理的には630

私はそれが存在する場合だと思うNow..the理由は、私はそれを削除して、このようSELECT COUNT(*)をすればということで読み取ります

select COUNT(*) 
      from dbo.T001_InventoryDetail o 
      where exists (select 1 
          from dbo.TXXX_InventoryFull i 
          where i.C001_AsOfDate= o.C001_AsOfDate 
          and i.C001_ProductID=o.C001_ProductID 
          and i.C001_StoreNumber=o.C001_StoreNumber 
          and [email protected] 
          and (i.C001_LastModelDate!=o.C001_LastModelDate 
            or o.C001_InventoryQty!=o.C001_InventoryQty 
            or i.C001_OnOrderQty!=o.C001_OnOrderQty 
            or i.C001_TBOQty!=o.C001_TBOQty 
            or i.C001_ModelQty!=o.C001_ModelQty 
            or i.C001_TBOAdjustQty!=o.C001_TBOAdjustQty 
            or i.C001_ReturnQtyPending!=o.C001_ReturnQtyPending 
            or i.C001_ReturnQtyInProcess!=o.C001_ReturnQtyInProcess 
            or i.C001_ReturnQtyDueOut!=o.C001_ReturnQtyDueOut)) 
       and [email protected] 
  • TXXX_InventoryFull '。スキャン回数41、論理読み取り回数692
  • T001_InventoryDe​​tail '。スキャンカウント65、論理読み取り値17477
  • ワークテーブル '。スキャン回数0、論理読み込み0
+0

CPUについてはどうですか? – gbn

答えて

0

私は、あなたが参加を利用するときに得られる計画がかなり異なると思います。おそらく、行数の不均衡(非常に大きな外部表、小さな内部表)により、オプティマイザの適合が得られますが、おそらくは結合がはるかに簡単に行を排除することができます。計画を見たり、再現できることなく、実際に推測するのは難しいですが、できるだけ計画の早い段階で最も多くの行を排除することを常に目標にすべきです。いくつかの演算子/サブクエリを通じた何百万行もの行を後で取り除くことは、後で計画の後半で大半を排除することは、ほぼ確実にパフォーマンスを低下させることになります。

1

SQL 08 R2サーバーでEXISTSステートメントを使用して同様の問題が検出されました.SQL 08とSQL 05ではまったく同じステートメントが正常に実行されます。

私は

WHILE EXISTS(SELECT * FROM X) 

のようなものを変更すると、超低速になるだろうがことがわかった:完全に速い再び

WHILE ISNULL((SELECT TOP 1 ID FROM X), 0) <> 0 

実行します。私に

、それはR2の問題のように思える...

2

一般的には、これらが結合し、ネストされたループを強制する傾向があるように、1つは、述語で協調サブクエリを行うことを避けるべきであるといわれています。大規模なデータセットを照会する場合、特にセット間の違いを発見しようとする場合、照会オプティマイザが、ハッシュ、マージおよびネストループのアルゴリズム間で動的に選択できるようにすることが重要です。 。 FROM句にこれらの派生テーブルを作成する方がよいでしょう。