2014-02-20 20 views
0

下面兩個查詢給出了相同的結果。 只是想知道哪一個在性能方面更好。哪個是編寫sql的最佳實踐

查詢1:

SELECT N.* 
FROM NOTIFICATIONS N 
     JOIN NOTIFICATION_COMPANY_GROUPS NCG 
      ON (N.COMPANY_ID = NCG.COMPANY_ID 
      AND N.ID = NCG.NOTIFICATION_ID) 
     JOIN COMPANY_USER_GROUPS CUG 
      ON (N.COMPANY_ID = CUG.COMPANY_ID 
      AND CUG.COMPANY_GROUP_ID = NCG.COMPANY_GROUP_ID) 
     JOIN NOTIFICATION_PROPERTIES NP ON (N.COMPANY_ID = NP.COMPANY_ID) 
     JOIN COMPANY_USER_PROPERTIES CUP 
      ON (N.COMPANY_ID = CUP.COMPANY_ID 
      AND CUP.PROPERTY_ID = NP.PROPERTY_ID) 
WHERE N.COMPANY_ID = 2138 
AND CUG.COMPANY_USER_ID = 41422 
AND CUP.COMPANY_USER_ID = 41422; 

查詢2:

SELECT N.* 
FROM NOTIFICATIONS N 
     JOIN NOTIFICATION_COMPANY_GROUPS NCG 
      ON (N.COMPANY_ID = 2138 
      AND N.COMPANY_ID = NCG.COMPANY_ID 
      AND N.ID = NCG.NOTIFICATION_ID) 
     JOIN COMPANY_USER_GROUPS CUG 
      ON (CUG.COMPANY_USER_ID = 41422 
      AND N.COMPANY_ID = CUG.COMPANY_ID 
      AND CUG.COMPANY_GROUP_ID = NCG.COMPANY_GROUP_ID) 
     JOIN NOTIFICATION_PROPERTIES NP ON (N.COMPANY_ID = NP.COMPANY_ID) 
     JOIN COMPANY_USER_PROPERTIES CUP 
      ON (CUP.COMPANY_USER_ID = 41422 
      AND N.COMPANY_ID = CUP.COMPANY_ID 
      AND CUP.PROPERTY_ID = NP.PROPERTY_ID); 
+0

查詢規劃人員應該對待這兩種形式 - 查看* special * SQL實現中的查詢計劃以查看是否有任何意外。這就是說,我建議所有(也是唯一的)JOIN術語放在'ON ..'位,以及'WHERE'中的所有其他位置。也就是說,我推薦第一種形式 - 我發現閱讀/理解更簡單,並且更容易生成,修改或集成到外部查詢中。 – user2864740

+0

爲什麼不測量它?剩下的事情:儘量寫出你的陳述儘可能容易理解(這有點關乎品味/思考方式)。這將更容易讓語句在語義上正確(並維護它們)。只有遇到性能問題,請嘗試其他方法。 (「不成熟的優化是萬惡之源」,D.E.Knuth說) – Ronald

回答

7

我所期望的性能應該是相同的,但你可以使用EXPLAIN驗證查詢計劃的相同。

但是,第一個版本是編寫它的「正確」方式。一般而言,ON條款應該只包含關聯表格的條件,而單個表格的條件應該在WHERE條款中。

唯一的例外是在LEFT JOIN條款,其中表加入的條件應該在ON條款。這是因爲,如果將它們放在WHERE子句中,則除非明確檢查NULL,否則主表中的行中沒有匹配表的行中的空行將被濾除。作爲一個例子:

SELECT ... 
FROM T1 
LEFT JOIN T2 ON T2.T1_id = T1.id AND T2.someCol = 3 

SELECT ... 
FROM T1 
LEFT JOIN T2 ON T2.T1_id = T1.id 
WHERE T2.someCol = 3 

在第一版本中,T2.someCol在測試接合之前完成;結果將包含來自T1的所有行,但在T2中沒有匹配行的將對所有T2列有NULL。但是第二個版本不會有任何這些不匹配的行,因爲聯接是先完成的,然後執行T2.someCol = 3測試;如果沒有匹配的T2行,則T2.someCol將爲NULL,並且此測試將失敗,並且該行將被WHERE過濾掉。

對於內連接,無論您在加入前還是之後進行比較,結果都是相同的。查詢規劃人員應該儘可能以最大程度地利用索引來排序這些索引。

+1

說「唯一的例外」​​的部分應該是粗體;這是很多錯誤的重要來源。 –

+0

我沒有看到有關左連接的部分。那是不是在談論簡單地移動固定術語(例如'cup.company_user_id = 41422')?或者是特指加盟條件? – user2864740

+0

我已經爲左連接添加了一個示例。 – Barmar