Sql-Server

查看列消除

  • March 19, 2018

當您只需要選擇特定的列時,我對查詢優化器如何從視圖的查詢中消除不必要的列感到有些困惑。

這是我的看法:

CREATE VIEW Schema1.Object1
AS
 SELECT Object2.Column1  AS Column2,
        Object2.Column3  AS Column4,
        Object3.Column5,
        Object3.Column6,
        Object4.Column1  AS Column7,
        Object5.Column1  AS Column8,
        Object5.Column9  AS Column10,
        Object5.Column11 AS Column12,
        Object5.Column13 AS Column14,
        Object5.Column15 AS Column16,
        Object5.Column17 AS Column18,
        Object5.Column19 AS Column20,
        Object5.Column21 AS Column22,
        Object5.Column23 AS Column24,
        CASE
          WHEN Object2.Column25 >= Object5.Column25
            THEN Object2.Column25
          ELSE Object5.Column25
        END              AS Column25,
        Object2.Column26
 FROM   Schema1.Object6 AS Object2
        CROSS JOIN Schema2.Object7 AS Object4
        JOIN Schema1.Object8 AS Object3
          ON Object3.Column5 = Object2.Column5
             AND Object3.Column7 = Object4.Column1
        LEFT JOIN Schema1.Object9 AS Object5
          ON Object5.Column4 = Object2.Column3
        JOIN Schema3.Object10 AS Object11
          ON Object5.Column26 = Object11.Column27 

現在,我只想進行如下查詢:

SELECT Column2 
FROM Schema1.Object1

…但是估計的計劃包括視圖中的所有列,即使查詢沒有返回它們。

為什麼會這樣?我可以避免這種情況嗎?

這是查詢計劃的連結:https ://1drv.ms/u/s!AhdjYi359YDTgYF6sLo8fBsj5H6Ilg

在此處輸入圖像描述

也可在https://www.brentozar.com/pastetheplan/?id=S1MhIB3Ff獲得

計劃中的每個節點僅投影正確滿足查詢所需的最低限度的列。您可以通過查看每個運算符的輸出列表來了解這一點。例如,最終連接僅列出一列。SQL Server 非常擅長刪除不需要的投影。

我想也許您期望消除一個或多個**聯接。**這更棘手,因為優化器必須小心不要改變查詢的含義。正如 Rob Farley在 SQL Server中的 JOIN 簡化中所描述的,有四個原因可以保持連接:

  1. 額外的列。需要連接來提供查詢所需的列,因為該列出現在最終結果中,或者某些中間步驟(如過濾或不同的連接)需要它。
  2. 行重複。連接可以增加匹配的行數。例如,表 A 中的單行可能與表 B 中的兩行連接,因此結果將包含表 A 行中資訊的兩個副本。
  3. 行消除。內連接可以消除表 A 中不與表 B 中的任何行連接的行。
  4. 添加了 NULL。右連接或完全連接可以引入新的 NULL,其中表 A 中的行與表 B 中的行不匹配。

SQL Server 在刪除不必要的連接方面做得很好(雖然不是完美的),但這樣做是安全的僅當優化器保證上述四種連接效果都不會影響結果時,才能刪除連接。

在您的情況下,上述第 2 項和第 3 項很可能適用。您可以通過使用左連接而不是內連接來使視圖更簡化,並且可能DISTINCT在您的外部查詢中添加一個。有關範例,請參見 Rob 的文章。

引用自:https://dba.stackexchange.com/questions/201609