有沒有辦法防止計算列中的標量 UDF 抑制並行性?
有關SQL Server中標量 UDF的危險的文章很多。隨意搜尋會返回大量結果。
不過,在某些地方,標量 UDF 是唯一的選擇。
例如:在處理 XML 時:XQuery 不能用作計算列定義。Microsoft 記錄的一種選擇是使用標量 UDF將 XQuery 封裝在標量 UDF 中,然後在計算列中使用它。
這有各種影響和一些解決方法。
- 查詢表時逐行執行
- 強制對錶的所有查詢串列執行
您可以通過模式綁定函式來繞過逐行執行,並保留計算列或對其進行索引。即使沒有引用標量 UDF,這些方法都不能阻止對錶的查詢的強制序列化。
有沒有已知的方法可以做到這一點?
是的,如果您:
- 正在執行 SQL Server 2014 或更高版本;和
- 能夠在跟踪標誌 176處於活動狀態的情況下執行查詢;和
- 計算列是
PERSISTED
具體來說,至少需要以下版本:
- SQL Server 2016 SP1 的累積更新 2
- SQL Server 2016 RTM 的累積更新 4
- SQL Server 2014 SP2 的累積更新 6
但是為了避免這些修復中引入的錯誤(參考2014和2016 和 2017 ),請改為應用:
- SQL Server 2017 的累積更新 1
- SQL Server 2016 SP1 的累積更新 5
- SQL Server 2016 RTM 的累積更新 8
- SQL Server 2014 SP2 的累積更新 8
跟踪標誌作為啟動
–T
選項有效,在全域和會話範圍內使用DBCC TRACEON
,以及使用OPTION (QUERYTRACEON)
計劃指南的每個查詢。跟踪標誌 176 防止持久計算列擴展。
編譯查詢時執行的初始元數據載入會引入所有列,而不僅僅是那些直接引用的列。這使得所有計算列定義都可用於匹配,這通常是一件好事。
作為一個不幸的副作用,如果載入的(計算的)列之一使用標量使用者定義函式,它的存在會禁用整個查詢的並行性,即使計算的列實際上沒有被使用。
跟踪標誌 176 有助於解決此問題,如果列是持久的,則不載入定義(因為跳過了擴展)。這樣,使用者定義的標量函式就不會出現在編譯查詢樹中,因此不會禁用並行性。
跟踪標誌 176 的主要缺點(除了很少記錄之外)是它還阻止查詢表達式匹配到持久計算列:如果查詢包含與持久計算列匹配的表達式,跟踪標誌 176 將防止表達式被替換為對計算列的引用。
有關更多詳細資訊,請參閱我的 SQLPerformance.com 文章Properly Persisted Computed Columns。
由於問題提到了 XML,作為使用計算列和標量函式提升值的替代方法,您還可以查看使用 Selective XML Index,正如您在Selective XML Indexes: Not Bad At All中所寫的那樣。