Sql-Server
多語句 TVF 上的 WITH SCHEMABINDING 是否會改善基數估計?
根據查詢性能和多語句表值函式等文章,SQL Server 假設多行表值函式返回一行。如果呼叫語句實際上返回許多行,這會導致為呼叫語句選擇一個糟糕的執行計劃。
添加
SCHEMABINDING
到函式是否會導致函式返回值集的基數估計更正確?如果我們假設我們將一個UserId傳遞給這個函式並返回一個允許使用者訪問的RecordId值表,並且一些使用者只被允許看到一些記錄,而一些使用者被允許看到很多甚至所有記錄,函式或呼叫語句(或包含它們的過程)是否會從使用中受益
RECOMPILE
?函式中的使用會SCHEMABINDING
改變這個答案嗎?我意識到我可以通過實驗來解決這個問題,但我希望有人已經找到了答案。指向有據可查的地方的指針會很有幫助。
在我的測試中,不,添加
WITH SCHEMABINDING
不會改善基數估計。我創建了一個簡單的表:CREATE TABLE dbo.myobjects(id INT PRIMARY KEY); INSERT dbo.myobjects SELECT [object_id] FROM sys.all_objects;
然後是兩個函式:
CREATE FUNCTION dbo.noschemabinding(@UserID INT) RETURNS @x TABLE (id INT) AS BEGIN INSERT @x SELECT id FROM dbo.myobjects; RETURN; END GO CREATE FUNCTION dbo.withschemabinding(@UserID INT) RETURNS @x TABLE (id INT) WITH SCHEMABINDING AS BEGIN INSERT @x SELECT id FROM dbo.myobjects; RETURN; END GO
比較實際計劃,兩者都顯示估計行 = 1,實際行 = 2112(後一個數字可能在您的系統上有所不同,具體取決於版本/SP 等)。
速度對比:
SET NOCOUNT ON; GO SELECT SYSDATETIME(); GO SELECT id INTO #x FROM dbo.noschemabinding(1); DROP TABLE #x; GO 1000 GO SELECT SYSDATETIME(); GO SELECT id INTO #x FROM dbo.withschemabinding(1); DROP TABLE #x; GO 1000 SELECT SYSDATETIME();
結果:
run 1 run 2 ---------------- ------------------ ------------------ No schemabinding 14632 milliseconds 14079 milliseconds Schemabinding 14251 milliseconds 13979 milliseconds
那麼,這很重要嗎?沒有。
SCHEMABINDING
在這種情況下,用於更重要的目標:底層架構穩定性。如果您追求將您的函式轉換為內聯 TVF,那麼您可能會有更好的優化機會,而不是在多語句 TVF 中尋找影響計劃的模糊差異。