Sql-Server

串聯物理操作:是否保證執行順序?

  • August 9, 2017

在標準 SQL 中,union all不保證 a 的結果是任何順序的。所以,像:

select 'A' as c union all select 'B'

可以以任何順序返回兩行(儘管實際上在我所知道的任何數據庫上,“A”將出現在“B”之前)。

在 SQL Server 中,這變成了使用“串聯”物理操作的執行計劃。

我可以很容易地想像連接操作會掃描它的輸入,返回任何有可用記錄的輸入。但是,我在網上找到了以下聲明(此處):

查詢處理器將按照運算符在計劃中出現的順序執行此計劃,第一個是最上面的,最後一個是結束的。

問題:這在實踐中是真的嗎?這能保證是真的嗎?

我沒有在 Microsoft 文件中找到任何參考,說明輸入是按順序掃描的,從第一個到最後一個。另一方面,每當我嘗試執行它時,結果表明輸入確實是按順序處理的。

有沒有辦法讓引擎一次處理多個輸入?我的測試(使用比常量複雜得多的表達式)是在支持並行的 8 核機器上進行的,並且大多數查詢確實利用了並行性。

,Microsoft 沒有文件保證該行為,因此無法保證

此外,假設 Simple Talk 文章是正確的,並且 Concatenation 物理運算符始終按照計劃中顯示的順序處理輸入(很可能是正確的),那麼不能保證 SQL Server 將始終生成保持相同的計劃查詢文本和查詢計劃之間的順序,你只是稍微好一點。

不過,我們可以進一步調查。如果查詢優化器能夠對串聯運算符輸入重新排序,則未記錄的 DMV 中應該存在sys.dm_exec_query_transformation_stats與該優化相對應的行。

SELECT * FROM sys.dm_exec_query_transformation_stats 
   WHERE name LIKE '%CON%' OR name LIKE '%UNIA%'

在 SQL Server 2012 Enterprise Edition 上,這會產生 24 行。忽略與常量相關的轉換的錯誤匹配,有一個與串聯物理運算符UNIAtoCON(Union All to Concatenation)相關的轉換。因此,在物理運算符級別,似乎一旦選擇了連接運算符,它將按照其派生的邏輯 Union All 運算符的順序進行處理。


事實上,這並不完全正確。存在優化後重寫,可以在基於成本的優化完成後對物理串聯運算符的輸入進行重新排序。一個範例發生在 Concatenation 受制於行目標時(因此首先從更便宜的輸入中讀取可能很重要)。有關詳細資訊,請參閱Paul White 的UNION ALL優化

後期物理重寫在 SQL Server 2008 R2 之前(包括 SQL Server 2008 R2)仍然有效,但回歸意味著它不再適用於 SQL Server 2012 及更高版本。已發布一個修復程序,在啟用查詢優化器修補程序(例如跟踪標誌 4199)的情況下恢復 SQL Server 2014 及更高版本(不是 2012 年)的這種重寫。


但是關於邏輯並集 All 運算符 ( UNIA) 呢?有一個UNIAReorderInputs轉換,可以重新排序輸入。還有兩個物理運算符可以用來實現邏輯Union All,UNIAtoCONUNIAtoMERGE(Union All to Merge Union)。

因此,查詢優化器似乎可以對 a 的輸入重新排序UNION ALL;但是,它似乎不是一種常見的轉換(UNIAReorderInputs在我很容易訪問的 SQL Server 上零使用。我們不知道會使用優化器的情況UNIAReorderInputs;儘管在計劃指南或使用時肯定會使用它計劃提示用於強制使用上述行目標物理重新排序輸入生成計劃。

有沒有辦法讓引擎一次處理多個輸入?

Concatenation 物理運算符可以存在於計劃的並行部分中。遇到一些困難,我能夠使用以下查詢生成具有並行連接的計劃:

SELECT userid, regdate  FROM (  --Users table is around 3mil rows
   SELECT  userid, RegDate FROM users WHERE userid > 1000000
   UNION 
   SELECT  userid, RegDate FROM users WHERE userid < 1000000
   UNION all
   SELECT userid, RegDate FROM users WHERE userid < 2000000
   ) d ORDER BY RegDate OPTION (RECOMPILE)

因此,從最嚴格的意義上說,物理串聯運算符似乎總是以一致的方式處理輸入(頂部第一,底部第二);但是,優化器可以在選擇物理運算符之前切換輸入的順序,或者使用合併聯合而不是串聯。

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