Sql-Server

為什麼沒有分區消除

  • April 30, 2019

我有一個臨時表#termin,其中包含 3 行

當我執行以下查詢時

SELECT t.termin, ttw.tourid, twt.va_nummer_int
 FROM #term AS t
INNER JOIN plinfo.t_touren_werbeflaechentermine AS ttw
    ON ttw.termin = t.termin
 INNER JOIN wtv.t_werbeflaechentermine AS twt 
    ON twt.jahr   = t.jahr
   AND twt.termin = t.termin
   AND twt.ID_Wt  = ttw.id_wt
   GROUP BY t.termin, ttw.tourid, twt.va_nummer_int

我將得到以下執行計劃: 在此處輸入圖像描述

每個表都使用匹配的索引連接。兩個表都由 ps_termin(termin) 分區。

對於第一個表 (t_touren_werbeflaechentermine),它會進行分區消除並只讀取行的一個子集,而對於第二個表 (t_werbeflaechentermine),它會掃描整個索引 ( jahr, termin, id_wt include (va_nummer_int))。

所以我的問題是:為什麼它是索引掃描(而不是搜尋),為什麼它不消除第二個表的分區。

PS:在WITH (FORCESEEK)第二個表上使用時,它會在執行計劃中切換兩個表,並對第一個表進行全索引掃描…

PPS:執行計劃可以在這裡找到

為什麼要進行索引掃描?

與 loop-seek 方法相比,SQL Server 估計掃描數據的成本可能更低(只有 1.7MM 行,因此是一個相對較小的表)。

掃描t_werbeflaechentermine表將處理所有1,708,658行,您的計劃表明這會執行7,347 logical reads

估計執行循環搜尋~70K seeks(循環外側的基數估計)。如果我們假設一次搜尋是二分搜尋,那麼我們可能會估計這將具有70109.4 * LOG(1708658,2)或的複雜度1,451,575

這比掃描處理的行數略低1,708,658,但邏輯讀取的數量會高得多,因為每個(估計的)~70K 搜尋將執行幾次邏輯讀取,產生比選擇的掃描更多的邏輯讀取。這可能是循環搜尋計劃產生更高的估計成本並且未被選中的原因。

無需掃描即可查看計劃

如果您想將此計劃與對兩個連接都使用循環搜尋的執行計劃進行比較,您可以嘗試將OPTION (LOOP JOIN)查詢提示添加到您的查詢中,以便兩個連接都使用循環連接。發布此實際執行計劃以進行比較將是有益的。

為什麼不消除分區?

我相信不會發生分區消除,t_werbeflaechentermine因為 SQL Server 沒有雜湊連接算法,該算法根據在雜湊連接的建構端觀察到的分區執行分區消除。在某些情況下,這將是一個很好的優化,但據我所知,在目前優化器中不可用:分區消除可用於循環連接的內側,但不適用於散列連接的探測側(除非查詢包含分區列上的顯式謂詞)。

為了進一步閱讀,SQL Server 確實具有並置聯接的概念,其中散列聯接獨立應用於以相同方式分區的兩個表的每個分區。但是,此優化僅適用於 2 路連接,因此您的查詢不符合條件。Paul White 在改進分區表連接性能中更詳細地描述了這個和其他分區表連接注意事項。

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