2011-04-12 63 views
10

我必須根據表上不存在的條件選擇一些行。如果我使用如下所示的聯合,它會在不到1秒的時間內執行。在SQL Server查詢中,UNION ALL與OR條件

SELECT 1 FROM dummyTable 
WHERE NOT EXISTS 
(

SELECT 1 FROM TABLE t 
WHERE Data1 = t.Col1 AND Data2=t.Col2 

UNION ALL 

SELECT 1 FROM TABLE t 
WHERE Data1 = t.Col2 AND Data2=t.Col1 

) 

但是,如果我使用OR條件,由於SQL服務器正在執行表懶惰池,因此需要將近一分鐘。有人可以解釋嗎?

SELECT 1 FROM dummyTable 
WHERE NOT EXISTS 
(

SELECT 1 FROM TABLE t 
WHERE ((Data1 = t.Col1 AND Data2=t.Col2) OR (Data1 = t.Col2 AND Data2=t.Col1)) 
) 

回答

2

查詢計劃也受到表中行數的影響。表t中有多少行?

您也可以嘗試:

SELECT 1 FROM dummyTable 
WHERE NOT EXISTS 
(
    SELECT 1 FROM TABLE t 
    WHERE Data1 = t.Col1 AND Data2=t.Col2 
) 
AND NOT EXISTS 
( 
    SELECT 1 FROM TABLE t 
    WHERE Data1 = t.Col2 AND Data2=t.Col1  
) 

或(糾正SQL服務器)這將使用索引:

WITH tt AS        <---- a temp table with 2 rows 
(SELECT Data1 AS Col1, Data2 AS Col2 
    UNION 
    SELECT Data2 AS Col1, Data1 AS Col2 
) 
SELECT 1 FROM dummyTable 
WHERE NOT EXISTS 
(
    SELECT 1 
    FROM TABLE t 
    JOIN tt      
     ON tt.Col1 = t.Col1 AND tt.Col2=t.Col2 
) 
+0

表中有800k行。我喜歡你提供的選項。目前我使用的是union,但我也可以使用AND NOT EXISTS選項。我主要想知道爲什麼「或」會有問題。我想它沒有使用任何索引,並且需要將值存儲在臨時表中以供比較。 – 2011-04-13 15:28:17

+0

我不指望我的'AND NOT EXISTS'解決方案比'UNION'更好。 (順便說一句,你爲什麼使用'UNION ALL'而不是'UNION'? – 2011-04-13 15:40:16

+0

我認爲union沒有進行任何分組/過濾,所以速度更快,所以我會相互排斥可以做所有的工會,是的,我不認爲和不存在會比聯盟所有表現更好,只是讀得更好 – 2011-04-13 19:14:29

1

OR的使用很可能導致查詢優化器在第二個查詢不再使用索引。看看每個查詢的解釋,並會告訴你答案。

+0

你可能是正確的。這是一種遞歸的查詢,執行計劃很複雜。要從中分辨出什麼並不容易。兩個查詢的大部分計劃看起來都是相同的。我想我會繼續使用UNION ALL。 – 2011-04-12 18:31:48

4

的問題是,你是不是以該指定的兩個條件適用於查詢中的單獨表格。因此,非聚簇索引seek必須返回大表中的大部分或全部行,因爲OR邏輯意味着它們也可能與第二個表中的condition子句相匹配。

查看上面所有三個示例中的SQL執行計劃,並注意來自大表中非聚簇索引seek的行數。最終結果可能只返回表中800,000行的1,000或更少,但OR子句意味着該表的內容必須與第二個表中的條件相互參照,因爲OR意味着它們可能需要用於最終查詢輸出。

根據您的執行計劃,索引seek可能會在大表中提取所有800,000行,因爲它們也可能與第二個表中的OR子句的條件匹配。 UNION ALL是每個對一個表的兩個單獨查詢,因此索引搜索只需輸出可能與該查詢的條件匹配的較小結果集。

我希望這是有道理的。我在重構慢速運行的SQL語句時遇到了同樣的情況。

乾杯,

安德烈·拉涅利