2009-08-25 67 views
0

SQL Server 2008.我有這個非常大的查詢,它具有很高的成本。 TOAD具有查詢優化功能,在它和做出的唯一改變是以下幾點:是char(3)現場查詢優化。 TOAD爲什麼要這樣做?

LEFT OUTER JOIN (SELECT RIN_EXT.rejected, 
           RIN_EXT.scar, 
           RIN.fcreceiver, 
           RIN.fcitemno 
          FROM dbo.rcinsp RIN 
           INNER JOIN RCINSP_EXT RIN_EXT 
            ON RIN.identity_column = COALESCE (RIN_EXT.fkey_id , RIN_EXT.fkey_id)) RIN1 
     ON RCI.freceiver = RIN1.fcreceiver 
      AND RCI.fitemno >= RIN1.fcitemno -- ***** RIGHT HERE 
      AND RCI.fitemno <= RIN1.fcitemno 
WHERE RED.[YEAR] = '2009' 

領域,這就是:

前:

LEFT OUTER JOIN (SELECT RIN_EXT.rejected, 
           RIN_EXT.scar, 
           RIN.fcreceiver, 
           RIN.fcitemno 
          FROM RCINSP_EXT RIN_EXT 
           INNER JOIN dbo.rcinsp RIN 
            ON RIN_EXT.fkey_id = RIN.identity_column) RIN1 
     ON RCI.freceiver = RIN1.fcreceiver 
      AND RCI.fitemno = RIN1.fcitemno 
WHERE RED.[YEAR] = '2009' 

後SQL Server 2008.

任何想法爲什麼他們比我的速度快得多?

+0

如果你注意到,他們做了RIN和INNER JOIN RIN_EXT,而你做了RIN_EXT和INNER JOIN RIN。不知道你是否錯過了其他的差異,也不知道你是否通過刪除了你評論過的那一行並且該特定行導致了性能提升。 – JustLoren 2009-08-25 18:33:19

+0

最佳選擇是比較2個查詢的查詢計劃,並查看他們正在使用哪些運算符。 – 2009-08-25 18:38:52

+0

對不起,我意識到第一個腳本丟失了其他連接標準。 – DavidStein 2009-08-25 19:03:12

回答

2

您在「Before」查詢中沒有顯示ON條件,所以我不知道TOAD是否發生了變化。但是,我會猜測發生了什麼。

SQL Server查詢優化器使用成本估計來選擇查詢計劃。成本估算基於行數估算。如果行數估算不準確,優化程序可能不會選擇最佳計劃。

某些行計算的估計值通常是準確的,如具有統計信息的列的表格(列=值)。但是,某些行計算的估計值只能在(column = othercolumn)列中被猜到,如果列與外鍵約束或(表達式=值)不相關,則表達式不是微不足道的或包含多個列。

當統計信息不指導行數估算值時,SQL Server使用通用估算值。如果將估計計劃中的rowcount估算值與實際計劃中的實際行數進行比較,則有時可以看到問題並「欺騙」優化器更改其行計數估算值。

如果使用AND添加謂詞並不實際限制結果,那麼如果優化程序無法識別它們是多餘的,則可以降低rowcount估計值。同樣,如果使用OR添加謂詞並不會實際產生額外結果,則可以提高行數估算值。

也許在這裏,行數估計過高,額外的謂詞正在糾正它們,從而導致更好的成本估算,並考慮更好的計劃選擇。

2

看起來像一個升序索引搜索參數的事情 - 因爲它增加了一個> = - 我們沒有看到足夠的關於其餘的查詢,但顯然有關於RCI.fitemno的進一步數據,它能夠從其餘的查詢。

很奇怪,這個:

 AND RCI.fitemno >= RIN1.fcitemno -- ***** RIGHT HERE 
     AND RCI.fitemno <= RIN1.fcitemno 

並沒有變成這樣:

 AND RCI.fitemno = RIN1.fcitemno 

因爲它們是等價的。

2

在查詢中添加大於和小於查詢是一種古老的技巧,有時會促使查詢優化器在該列上使用索引。因此,這個技巧:

AND RCI.fitemno >= RIN1.fcitemno 
AND RCI.fitemno <= RIN1.fcitemno 

強制數據庫使用RIN1和RCI fitemno列上的索引(如果存在)。我不確定在執行此操作時是否會臨時創建臨時索引。

我曾經用DB2數據庫來做這些技巧,而且他們工作得很好。