2009-04-28 59 views
11

在常規的JOIN中顯式地進行HASH JOIN(其中SQL Server將決定最佳的JOIN策略)有什麼優點?例如:指定HASH JOIN剛剛進行JOIN的優點?

select pd.* 
from profiledata pd 
inner hash join profiledatavalue val on val.profiledataid=pd.id 

在上面的簡單示例代碼中,我指定的連接策略,而如果我離開掀起的「哈希」鍵字SQL Server將做一個合併連接幕後(根據「實際執行計劃「)。

回答

12

該optmiser做一個足夠好的工作日常使用。然而,從理論上講,可能需要3周的時間才能找到完美的計劃,因此有可能生成的計劃不會很理想。

除非你有一個非常複雜的查詢或大量的數據,它根本無法制定出好的計劃,否則我會放棄它。然後我會考慮它。

但隨着時間的推移,隨着數據更改/增長或索引更改等,您的JOIN提示將變爲過時並且阻止了最佳計劃。 JOIN提示只能在開發時使用該組數據進行單個查詢優化。

個人而言,我從來沒有在任何生產代碼中指定JOIN提示。

我通常通過改變我的查詢,添加/更改索引或分解索引(例如,首先加載臨時表)來解決不良連接問題。或者我的查詢是錯誤的,或者我有一個隱含的數據類型轉換,或者它突出顯示了我的模式等缺陷。

我見過其他開發人員使用它們,但只有他們有複雜視圖嵌套在複雜視圖和他們在重構時會引發更多的問題。

編輯:

我今天的一些同事打算用它們來迫使一個壞的查詢計劃(與NOLOCK和MAXDOP 1)從傳統的複雜的嵌套意見「鼓勵」遷移走了一個轉換是一個他們的下游系統直接調用。

0

邏輯計劃優化器不能保證它找到最佳解決方案:精確算法太慢而無法在生產服務器中使用;而是使用了一些貪婪的算法。

因此,這些命令背後的基本原理是讓用戶指定最佳連接策略,如果優化器無法理清什麼是最佳採用的。

2

散列連接並行化和縮放比其他任何連接都更好,並且非常適合數據倉庫中吞吐量的最大化。

1

我在運輸代碼中見過的唯一提示是OPTION(FORCE ORDER)。 SQL查詢優化器中的愚蠢錯誤會生成一個試圖加入未過濾的varchar和唯一標識符的計劃。增加FORCE ORDER導致它首先運行過濾器。

我知道,重載列是不好的。有時候,你必須忍受它。

+0

編輯我即將添加一個選項(MAXDOP 1),以防止後臺工作人員咀嚼所有處理器的能力。 – Joshua 2009-09-10 21:28:59

3

當嘗試一個哈希提示,怎麼樣:

  • 檢查的 表中的至少一個存在充分的指標之後。
  • 嘗試重新安排查詢後。像轉換 的東西加入到「中」或「存在」,改變連接順序(這是唯一一個真正的 提示反正),從where子句加盟條件移動邏輯等

一些基本的規則,規定當當連接條件不存在作爲表索引和表大小不同時,散列連接有效。如果你在尋找一個技術描述,那麼關於哈希連接的工作方式有一些很好的描述。

爲什麼使用任何連接提示(散列/合併/循環與強制順序的副作用)?

  • 爲了避免極端情況下執行速度極慢(.5 - > 10.0s)。
  • 當優化器一致選擇一個平庸的計劃。

提供的提示可能對某些情況不是理想的,但會提供更一致的可預測運行時。預期的最壞情況和最佳情況應該在使用提示時進行預先測試。可預測的運行時間對於web服務來說至關重要,在這些服務中,比起可以使用[.25,10.0s]的範圍,嚴格優化的標稱[.3s,.6s]查詢更受歡迎。隨着統計數據剛剛更新並遵循最佳實踐,可能會發生較大的運行時差異。

在開發環境中測試時,應該關閉「作弊」以避免熱/冷運行時差異。從另一個post ...

CHECKPOINT -- flushes dirty pages to disk 
DBCC DROPCLEANBUFFERS -- clears data cache 
DBCC FREEPROCCACHE -- clears execution plan cache 

最後的選擇可能是一樣的選項(重新編譯)提示。

MAXDOP和機器的加載也可以在運行時產生巨大的差異。將CTE物化到臨時表中也是一種很好的鎖定機制,需要考慮。