為什麼 Parallelism (Repartition Streams) Operator 會將 Row Estimates 減少到 1?
我正在使用 SQL Server 2012 企業版。我遇到了一個 SQL 計劃,它表現出一些我不覺得完全直覺的行為。在大量並行索引掃描操作之後,發生並行(重新分區流)操作,但它正在殺死索引掃描(Object10.Index2)返回的行估計,將估計減少到 1。我做了一些搜尋,但是沒有遇到任何解釋這種行為的東西。查詢非常簡單,儘管每個表都包含數百萬的記錄。這是 DWH 載入過程的一部分,這個中間數據集在整個過程中被觸及了幾次,但我遇到的問題尤其與行估計有關。有人可以解釋為什麼在 Parallelism (Repartition Strems) Operator 中準確的行估計會變為 1 嗎?還,
我已將完整計劃發佈到粘貼計劃。
這是有問題的操作:
包括計劃樹以防添加更多上下文:
我會遇到 Paul White 送出的這個 Connect 項目的一些變體嗎(在他的部落格上進一步深入解釋)?至少它是我發現的唯一一個似乎與我遇到的情況很接近的東西,即使沒有 TOP 操作員在玩。
帶有點陣圖過濾器的查詢計劃有時難以閱讀。來自重新分區流的 BOL 文章(強調我的):
Repartition Streams 運算符使用多個流並生成多個記錄流。記錄內容和格式不變。如果查詢優化器使用點陣圖過濾器,則輸出流中的行數會減少。
此外,關於點陣圖濾鏡的文章也很有幫助:
在分析包含點陣圖過濾的執行計劃時,了解數據如何在計劃中流動以及應用過濾的位置非常重要。點陣圖過濾器和優化點陣圖是在雜湊連接的建構輸入(維度表)一側創建的;但是,實際過濾通常在 Parallelism 運算符中完成,該運算符位於散列連接的探測輸入(事實表)一側。但是,當點陣圖過濾器基於整數列時,過濾器可以直接應用於初始表或索引掃描操作,而不是並行操作符。這種技術稱為行內優化。
我相信這就是您在查詢中觀察到的。可以提出一個相對簡單的展示來顯示重新分區流運算符減少基數估計,即使點陣圖運算符
IN_ROW
與事實表相反。資料準備:create table outer_tbl (ID BIGINT NOT NULL); INSERT INTO outer_tbl WITH (TABLOCK) SELECT TOP (1000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM master..spt_values; create table inner_tbl_1 (ID BIGINT NULL); create table inner_tbl_2 (ID BIGINT NULL); INSERT INTO inner_tbl_1 WITH (TABLOCK) SELECT (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) / 2000000 - 2) NUM FROM master..spt_values t1 CROSS JOIN master..spt_values t2; INSERT INTO inner_tbl_2 WITH (TABLOCK) SELECT (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) / 2000000 - 2) NUM FROM master..spt_values t1 CROSS JOIN master..spt_values t2;
這是您不應該執行的查詢:
SELECT * FROM outer_tbl o INNER JOIN inner_tbl_1 i ON o.ID = i.ID INNER JOIN inner_tbl_2 i2 ON o.ID = i2.ID OPTION (HASH JOIN, QUERYTRACEON 9481, QUERYTRACEON 8649);
我上傳了計劃。看看附近的運營商
inner_tbl_2
:您還可能會發現Paul White在Hash Joins on Nullable Columns中的第二個測試很有幫助。
在如何應用行縮減方面存在一些不一致。我只能在至少有三張桌子的計劃中看到它。但是,使用正確的數據分佈,預期行數的減少似乎是合理的。假設事實表中的連接列有許多在維度表中不存在的重複值。點陣圖過濾器可能會在這些行到達連接之前消除它們。對於您的查詢,估計值一直減少到 1。行在散列函式中的分佈方式提供了一個很好的提示:
基於此,我懷疑您的
Object1.Column21
列有很多重複值。如果重複的列碰巧不在統計直方圖中,Object4.Column19
那麼 SQL Server 可能會得到非常錯誤的基數估計。我認為您應該擔心可能會提高查詢的性能。當然,如果查詢滿足響應時間或 SLA 要求,則可能不值得進一步調查。但是,如果您確實希望進一步調查,您可以做一些事情(除了更新統計資訊)來了解如果查詢優化器有更好的資訊,它是否會選擇更好的計劃。您可以將連接的結果
Database1.Schema1.Object10
放入Database1.Schema1.Object11
臨時表中,然後查看是否繼續獲得嵌套循環連接。您可以將該連接更改為 aLEFT OUTER JOIN
,這樣查詢優化器就不會在該步驟減少行數。您可以MAXDOP 1
在查詢中添加提示以查看會發生什麼。你可以使用TOP
連同派生表一起強制連接到最後,或者您甚至可以從查詢中註釋掉連接。希望這些建議足以讓您入門。關於問題中的連接項,它與您的問題有關的可能性極小。這個問題與糟糕的行估計無關。它與並行的競爭條件有關,導致在後台的查詢計劃中處理太多行。在這裡,您的查詢似乎沒有做任何額外的工作。