2012-03-29 67 views
12

我的google-fu和so-fu在這裏失敗了,所以我不妨問一下。TSQL - 什麼是連接表的正確順序?

我有很多查詢與他們中的多個聯接。

在一個查詢中,我將標題/項目/細節連接在一起,並查找這些記錄的各種信息位。

加入時,我儘量保持它們的相關性。例如:我的標題有兩個查找表,所以在加入我的物品表之前,我會加入這些表。

這是正確的嗎?

在查找表之前加入較大的表是否更好?或相反亦然?

我應該在加入到小型表格時使用loop提示,並且在加入openrowsets時應該使用merge提示嗎?

我確定答案是「取決於」,但一些有效聯接的一般指導方針將非常有幫助。謝謝!

+0

在大多數情況下,您不需要指定連接的類型(合併/循環/散列)。如果你這樣做,那麼應該可以解決潛在的問題,而不是加入提示創可貼。 – 2012-03-29 14:59:57

+2

除非您非常清楚自己在做什麼,並且瞭解查詢執行計劃,否則請勿使用查詢提示。 – JotaBe 2012-03-29 17:55:21

回答

12

編輯:根據你的問題(和柯克沃爾的)評論,你應該明白order of your joins is aesthetic, and does not directly impact the resulting execution plan。查詢優化器將以最有效的順序執行連接,並在絕大多數時間使用適當的連接操作,而不需要任何提示。

當談到你的連接順序的美學時,這是有點主觀的,但我會說,以任何順序將你的表連接在一起使得通過查詢閱讀時有邏輯意義...如果你以@HeaderId開頭,與該表開始,然後JOIN給孩子表:

FROM 
    Header h 
    JOIN Items i ON h.HeaderId = i.HeaderId 
    JOIN Details d ON i.ItemId = d.ItemId 
WHERE 
    h.HeaderId = @HeaderId 

但是,如果你開始用@DetailId您的查詢,我會加入以相反的順序。

FROM 
    Details d 
    JOIN Items i ON d.ItemId = i.ItemId 
    JOIN Header h ON i.HeaderId = h.HeaderId 
WHERE 
    d.DetailId = @DetailId 

但是,這是主觀的,只是我個人的偏好。

當您開始包含OUTER JOIN s時,它會變得不那麼主觀...嘗試構建您的查詢以避免任何RIGHT OUTER JOIN s,而是使用LEFT OUTER JOIN's。

默認情況下不要使用聯接提示......實際上你幾乎從不使用它們。查詢優化器在選擇最佳執行計劃方面做得非常好。我只遇到了一個需要提供連接提示以改進計劃的單個實例......它極大地幫助了當時正在運行查詢的服務器,但是當數據庫遷移到不同的服務器時,我的加入提示破壞了查詢的性能。因此,重申一下,提供聯合提示通常是一個糟糕的主意。

+1

也許OP不知道連接順序與執行計劃無關,並且純粹是唯美的? – 2012-03-29 14:44:54

+0

@KirkWoll這是一個很好的觀點,我忽略了...我會在我的答案中澄清。 – 2012-03-29 14:47:09

+0

@Kirk,這正是我問的原因。訂單根本不相關? – IronicMuffin 2012-03-29 14:47:31

0

這個順序在很大程度上是審美的,但我認爲爲了避免混淆,在表的順序和條件中都有一個約定是有用的。

查詢提示僅適用於特殊情況,雖然您可能會發現需要使用它們的情況(通常會犧牲性能以降低併發問題),但您應該始終嘗試找到解決問題的更可靠方法。

[1] 我知道在哪裏的順序問題確實1案件:

CREATE TABLE A (
    id int IDENTITY PRIMARY KEY, 
    name varchar 
); 

CREATE TABLE B (
    id int IDENTITY PRIMARY KEY, 
    a_id int FOREIGN KEY REFERENCES A (id), 
    name varchar 
); 

SELECT * 
FROM A 
INNER LOOP JOIN B on A.id = B.a_id; 

SELECT * 
FROM B 
INNER LOOP JOIN A on A.id = B.a_id; 

的第一選擇做兩次索引掃描,第二做了掃描和尋道。這是避免提示的另一個很好的理由。

相關問題