2012-03-29 43 views
1

我有一個視圖,這是一個連接的集合。爲了這個問題的目的,我將簡化如下的觀點。注意,Table1.Table1ID是主鍵,Table2.Table1ID是外鍵。SQL Server視圖執行計劃:是否與UNION相同?

CREATE VIEW [View1] AS 
SELECT t1.Column1, t2.Column2 
FROM Table1 t1 
JOIN Table2 t2 ON t1.Table1ID = t2.Table1ID 

使用用於此目的的觀點是好的,因爲它減少了加入我在我的代碼做的數量,並允許SQL Server更有效地優化了連接。例如:

SELECT Column1, Column2 
FROM View1 
WHERE Column1 = 'abc' 
AND Column2 = 'xyz' 
GROUP BY Column1, Column2 

SQL服務器通過接合只從表1記錄,其中在列1的值是「ABC」和來自表2的記錄的子集,其中在列2的值是「XYZ」的子集優化上述查詢。換句話說,在應用連接之前,SQL Server執行計劃巧妙地將過濾應用於視圖中的相應表,從而減少了需要在連接中記錄的記錄數。

但是,如果我通過改變WHERE子句中AND運營商的運營商OR改變前查詢,執行計劃確實執行聯接之前應用的篩選。

SELECT Column1, Column2 
FROM View1 
WHERE Column1 = 'abc' 
OR Column2 = 'xyz' 
GROUP BY Column1, Column2 

上述查詢的執行計劃首先連接來自Table1和Table2的所有記錄,然後應用where子句秒。這符合布爾邏輯,因爲在連接表並且列1和列2中的值存在並佔據之前,不能滿足OR運算符測試。

另一方面,以下查詢返回與前一個查詢相同的結果集。

SELECT Column1, Column2 
FROM View1 
WHERE Column1 = 'abc' 
UNION 
SELECT Column1, Column2 
FROM View1 
WHERE Column2 = 'xyz' 

後者兩個查詢產生相同的結果,但兩者中的第二個由SQL Server,使得執行計劃應用where子句的各表中的各SELECT語句聯接是spplied之前優化在視圖中,導致加入的記錄更少。這將導致更高效的查詢,即使視圖實際上被調用了兩次,並且結果記錄集的交集被UNION返回。

我的問題是:

  • 爲什麼不SQL Server的優化使用類似於過去的查詢執行計劃的倒數第二個查詢?
  • 有沒有辦法定義視圖,以便SQL Server使用類似於最後一個查詢的執行計劃來優化它?

謝謝。

+2

最後的查詢是*不*相等 - 因爲'UNION'消除重複 - 我猜測你在測試數據中沒有重複*,但這不是一個普遍安全的假設。 – 2012-03-29 07:00:06

+0

@Damien_The_Unbeliever:好的。我離開了關鍵部分。 'GROUP BY'。 – Kuyenda 2012-03-29 16:44:20

回答

0

WHERE ... OR ...是與UNION不同的查詢。如果單個行的值爲abc,Column1xyz,Column2它將在WHERE ... OR ...的情況下只產生一行,而在UNION的情況下只產生兩行。你可能會爭辯UNION刪除重複項(因爲不是UNION ALL),我說這是一個簡化的例子,省略了其他正在投影的列。但即使考慮這個例子,我可以給出另一種情況,其中兩行行的值爲abc,對於Column1xyz對於Column2,並且在這種情況下,第一個查詢返回兩行,而第二個返回1.QED,優化你期望不會發生,因爲不正確。

+0

道歉。我離開了最初查詢的關鍵部分。 「GROUP BY」子句。每當我從視圖中查詢時,我都會選擇所有列,以便獲得離散的記錄集。 – Kuyenda 2012-03-29 16:48:49

0

爲什麼SQL Server不使用類似於最後一個查詢的執行計劃來優化倒數第二個查詢?

它可以做一個類似於你提供的例子的轉換。你需要弄清楚Remus的答案中提到的細節。我很確定這是可行的。例如,您可以使用這樣一個事實,即您可以將UNION重寫爲FULL OUTER JOIN。這使您可以插入正確的重複數據刪除條件。

此轉換未於2012年實施。這很不幸,但產品團隊無論如何都無法提供完美的優化器。我們擁有的非常好。

有沒有一種方法來定義視圖,以便SQL Server使用類似於最後一個查詢的執行計劃來優化它?

不是我所知道的。

我知道這個答案不會改善你的事情,但這就是這種情況。現在,考慮創建一個索引視圖。這樣您就可以預先生成您感興趣的行的子集。您可以創建跨多個表的列的索引。你可以索引表達式。