2011-04-21 16 views
1

可疑的性能這是在一個存儲過程..這if語句,然後我做一些工作。 @AsOfDate是傳入的變量日期數據類型。我的問題是爲什麼我通過刪除最內部存在的方式來獲得更好的性能,但只有當整個語句處於IF EXISTS使用IF EXISTS與內部存在檢查

兩個表:

  • dbo.TXXX_InventoryDe​​tail - 1.3十億records..stats最新
  • dbo.TXXX_InventoryFull - 980萬個records..stats最新

聲明:

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]) 

IO輸出:

  • 表'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 2011-04-21 13:48:55

回答

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

人們一般說,應該避免在謂語做協調的子查詢,因爲這些往往迫使嵌套循環聯接。在查詢大型數據集時,尤其是在試圖發現集合之間的差異時,允許查詢優化器在哈希,合併和嵌套循環算法之間動態選擇是很重要的,如果查詢是使用協調子查詢構建的。最好在FROM子句中將它們創建爲派生表。