2009-09-08 57 views
7

我有一個基本查詢,從6秒到1秒,只需將一個連接從LEFT JOIN更改爲LEFT HASH JOIN或'左循環連接'即可。任何人都可以解釋爲什麼這會導致性能如此之大的增加,以及爲什麼SQL的優化器不能自行找出它?爲什麼'HASH JOIN'或'LOOP JOIN'改善了這個存儲過程?

這裏大致是SQL的樣子:

SELECT 
    a.[ID] 
FROM 
    [TableA] a 
LEFT HASH JOIN 
    [TableB] b 
    ON b.[ID] = a.[TableB_ID] 
JOIN 
    [TableC] c 
    ON c.[ID] = a.[TableC_ID] 
WHERE 
    a.[SomeDate] IS NULL AND 
    a.[SomeStatus] IN ('X', 'Y', 'Z') AND 
    c.[SomethingElse] = 'ABC' 

表A和B具有數以百萬計的記錄和索引的所有ID字段。使用SQL Server 2005.

編輯:一個同事提出了一個左循環加入,它似乎使它更快...... SQL不是我的優勢之一,所以我想了解這些「提示」正在幫助。

+0

您可以在應用提示之前發佈計劃嗎?只需發出'SET SHOWPLAN_TEXT ON GO SELECT ...' – Quassnoi 2009-09-08 18:43:30

+0

刪除所有提示,然後在顯示實際計劃中在SSMS中運行查詢,然後在計劃中將預計行數與掃描/查找操作符的實際行數進行比較計劃。該計劃基於*估計*計數生成,持續時間由*實際*計數驅動。差異表示不好的統計數據,但也可能發生不尋常的奇數值的良好統計數據(例如,恰好有1密耳行數不爲10的SomeStatus)。 – 2009-09-08 18:54:49

回答

6

HASH JOIN在大部分行對結果集有貢獻時非常有用。

在你的情況,構建HASH TABLE在任AB和掃描另一個表是比任何在指數上B.ID執行NESTED LOOPS或合併該優化程序的提示之前所使用的排序結果集便宜。

SQL Server的優化程序沒有看到:可能是因爲您沒有收集統計​​信息,可能是因爲您的數據分佈有偏差。

更新:

由於你提到LOOP JOIN提高了速度,可能使得JOIN訂單是由優化器選擇不正確。

+0

在這種情況下,幾乎所有的行都應該成功加入(例如,90%+)。 – Kelsey 2009-09-08 18:40:34

+0

固定分配/分配。另外:看起來你終於通過了我在sql-server統計頁面上的總票數。我毫不猶豫地承認你對這個話題更加了解,所以這個世界現在只是一個不那麼古怪的人。 http://stackoverflow.com/questions/tagged?tagnames=sql-server&sort=stats&pagesize=30 – 2009-09-08 18:48:52

+0

謝謝,你的回答幫助我理解了這是爲什麼發生。 – Kelsey 2009-09-09 15:14:45