簡體   English   中英

SQL Server視圖執行計划:是在哪里還是與UNION相同?

[英]SQL Server View Execution Plan: Is WHERE OR the Same as UNION?

我認為這是聯接的集合。 出於這個問題的目的,我將簡化以下觀點。 注意, Table1.Table1ID是主鍵, Table2.Table1ID是外鍵。

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 Server通過僅聯接來自Table1的記錄子集(其中Column1中的值為“ abc”)和來自Table2的記錄子集(其中Column2中的值為“ xyz”)來優化上述查詢。 換句話說,SQL Server執行計划在應用聯接之前將篩選巧妙地應用於視圖中的各個表,從而減少了聯接中需要考慮的記錄數。

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

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

上面查詢的執行計划首先連接Table1和Table2中的所有記錄,然后再應用where子句。 這符合布爾邏輯,因為在連接表並且同時存在並考慮Column1和Column2中的值之前,不能滿足OR運算符測試。

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

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

后兩個查詢產生相同的結果,但是兩個查詢中的第二個由SQL Server優化,以便執行計划在聯接中拆分視圖之前將where子句應用於各個SELECT語句中的各個表,從而減少了查詢記錄被加入。 即使實際上兩次調用了該視圖,並且UNION返回了結果記錄集的交集,這也會導致總體上更高效的查詢。

我的問題是:

  • 為什么SQL Server不使用類似於上一個查詢的執行計划來優化倒數第二個查詢?
  • 有沒有一種方法可以定義視圖,以便SQL Server使用類似於上一個查詢的執行計划對其進行優化?

謝謝。

為什么SQL Server不使用類似於上一個查詢的執行計划來優化倒數第二個查詢?

它可以進行與您提供的示例相似的轉換。 您需要計算Remus答案中提到的細節。 我很確定這是可行的。 例如,您可以使用可以將UNION重寫為FULL OUTER JOIN的事實。 這樣就可以插入正確的重復數據刪除條件。

截至2012年,該轉換尚未實現。這是不幸的,但是產品團隊仍然無法提供理想的優化器。 我們擁有的相當不錯。

有沒有一種方法可以定義視圖,以便SQL Server使用類似於上一個查詢的執行計划對其進行優化?

從來沒聽說過。

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

WHERE ... OR ...是與UNION不同的查詢。 如果單行出現值abcColumn1xyzColumn2會產生只有一個行WHERE ... OR ...如此,但在兩行UNION情況。 您可能會說UNION刪除重復項(因為不是UNION ALL ),我說這是一個簡化的示例,它忽略了其他正在投影的列。 但即使考慮到這個例子廣告literam然后我就可以給其中行的值分別為另一種情況abcColumn1xyzColumn2 ,而第二個返回1 QED,優化你期望,在這種情況下,第一個查詢返回兩行,不能發生是因為不正確。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM