2012-09-09 47 views
1

我有2個表中有幾個相同的字段需要鏈接JOIN條件。例如。在每個表中都有字段:P1,P2。我想寫以下連接查詢:INNER JOIN與複雜的條件大大增加了執行時間

SELECT ... FROM Table1 
    INNER JOIN 
    Table2 
     ON Table1.P1 = Table2.P1 
     OR Table1.P2 = Table2.P2 
     OR Table1.P1 = Table2.P2 
     OR Table1.P2 = Table2.P1 

在這種情況下我有這樣的要求被執行了大量的時間巨大的表。

我試圖測試多長時間只有一個條件的查詢請求。首先,我已經用這種方式修改了表中的所有數據,其中P2 &P1被複製爲表1 &表2中的新行。所以我的查詢很簡單:

SELECT ... FROM Table1 INNER JOIN Table2 ON Table1.P = Table2.P 

其結果是更多然後驚訝:從多個小時(第一種情況下)的執行時間減少到2-3秒!

爲什麼它如此不同?這是否意味着複雜的條件總是會降低性能?我怎樣才能改善這個問題?可能是P1,P2索引會有幫助嗎?我想保持第一DB模式,而不是轉移到一個外地P.

+0

那些'OR's連接條件應該是'AND'還是那個故意? – Vikdor

+0

從外觀上看,這是故意的。匹配是Table1的P1或P2等於table2的P1或P2 – DarK

+4

可能的重複[在INNER JOIN條件中有'OR'是一個壞主意?](http://stackoverflow.com/questions/5901791/is-having -an-or-in-an-inner-join-condition-a-bad-idea) –

回答

2

可以使用4查詢和聯盟有導致

SELECT ... FROM Table1 
INNER JOIN 
Table2 
    ON Table1.P1 = Table2.P1 
UNION 
SELECT ... FROM Table1 
INNER JOIN 
Table2 
    ON Table1.P1 = Table2.P2 
UNION 
SELECT ... FROM Table1 
INNER JOIN 
Table2 
    ON Table1.P2 = Table2.P1 
UNION 
SELECT ... FROM Table1 
INNER JOIN 
Table2 
    ON Table1.P2 = Table2.P2 
+0

這將擴展到與OP相同的查詢。它仍然會以嵌套循環連接結束。 –

+0

@Kaushal,10倍!第二個建議很快,所以我會使用它。 但是還是不明白這是僅僅是MS SQL還是常見問題? – Sergey

+0

+1爲聯合解決方案,一些rdbms將根據其他CBO變量自動將多個OR標準轉換爲聯合 – gordy

0

是否使用CTE有助於提高性能?

;WITH Table1_cte 
AS 
(
SELECT 
     ... 
     [P] = P1 
FROM Table1 
UNION 
SELECT 
     ... 
     [P] = P2 
FROM Table1 
) 
, Table2_cte 
AS 
(
SELECT 
     ... 
     [P] = P1 
FROM Table2 
UNION 
SELECT 
     ... 
     [P] = P2 
FROM Table2 
) 
SELECT ... FROM Table1_cte x 
    INNER JOIN 
    Table2_cte y 
     ON x.P = y.P 

我懷疑,就處理器而言,以上只是針對相同複雜條件的不同語法。

4

查詢不同的原因是由於優化程序正在使用連接策略。基本上有四種方式這兩個表可以加入:

  1. 「散列連接」:創建於它用來查找在第二個值的表中的一個哈希表。
  2. 「合併連接」:對鍵上的兩個表進行排序,然後依次爲連接讀取結果。
  3. 「索引查找」:使用索引在一個表中查找值。
  4. 「嵌套循環」:將每個表中的每個值與另一個表中的所有值進行比較。

(並且在這些方面存在不同,例如使用索引而不是表,使用分區和處理多個處理器)。不幸的是,在SQL Server Management Studio中,(3)和(4)都是顯示爲嵌套循環連接。如果仔細觀察,可以從節點中的參數中區分出來。

在任何情況下,您的原始連接都是前三個之一 - 並且速度很快。這些連接基本上只能用於「等連接」。也就是說,當連接兩個表的條​​件包含一個相等運算符時。

當您從一個等式切換到「in」或「或」條件集合時,連接條件已從equijoin更改爲non-equijoin。我的觀察是,SQL Server在這種情況下做了一個糟糕的優化工作(並且公平地說,我認爲其他數據庫的工作幾乎完全相同)。您的性能打擊是從良好的連接算法到嵌套循環算法的命中。

沒有測試,我可能會提出以下一些策略。

  1. 在兩個表中的P1和P2上構建一個索引。 SQL Server可能會使用索引,即使是非等值鏈接。
  2. 使用另一個解決方案中建議的聯合查詢。每個查詢都應該正確優化。
  3. 假設這些都是1-1的連接,您也可以做到這一點作爲一個組多個聯接:

    從表1 T1留在t1.p1 = t2_11.p1外連接 表2 t2_11 左外連接 在t1.p1 = t2_12.p2表2 t2_12 左外連接 表2 t2_21 上t1.p2 = t2_21.p2左外連接 表2 t2_22 上t1.p2 = t2_22.p2

而n在SELECT中使用大小寫/合併邏輯來獲取您實際需要的值。雖然這看起來可能更復雜,但它應該非常有效。