Sql-Server
UDF 和內置函式行為
進行以下查詢:
DECLARE @X VARCHAR(200) = '1,2,3,4' SELECT *, dbo.aUserDefinedScalarFunction(4) AS ScalarValue FROM MyTable T INNER JOIN dbo.aUserDefineTableFunction(@X) A ON T.SomeID=A.SomeID WHERE (T.ID1 IS NULL OR T.ID1 IN (SELECT [value] FROM STRING_SPLIT(@X,','))) AND (T.ID2 IS NULL OR T.ID2 IN (SELECT Value FROM dbo.MySplitterFunction(@X))
我通常為上述條件創建索引#tempTables
WHERE
,我發現它在大型數據集上表現更好。但是,我仍然無法找到以下問題的明確答案:
- 查詢分析器會將 aUserDefinedScalarFunction(4) 優化為 ScalarValue 還是針對每條記錄進行評估?
- INNER JOIN dbo.aUserDefineTableFunction(@X) 會在臨時表中實現一次,還是會為每條記錄執行?該函式返回表(不是表變數)。
- SELECT 的結果是否
$$ value $$FROM STRING_SPLIT(@X,’,’) 得到優化還是針對每次比較進行評估? 4. SELECT Value FROM dbo.MySplitterFunction(@X) 的結果是否得到優化或在每次比較期間進行評估?
- 這取決於功能。對於使用schemabinding指定的**確定性函式,優化器通常只能評估其結果一次,並記憶體答案。
有關詳細資訊,請參閱:
- 內聯表值函式在優化之前擴展為呼叫查詢文本,因此沒有特殊機會進行早期評估和記憶體。這並不意味著執行計劃不會包含任何記憶體和重用優化。在適用的情況下,優化器將考慮那些(例如假離線),就像它對沒有內聯函式的查詢一樣。
- 通常,優化器將能夠判斷
SPLIT_STRING
在恆定輸入上返回確定性結果。該計劃可能只評估一次拆分,但這確實取決於計劃的形狀。- 假設 splitter 函式是一個多語句表值函式,那麼結果很可能只求值一次。有關詳細資訊,以及如何判斷執行計劃中是否發生記憶體,請參閱:
綜上所述,你對這一切保持謹慎是對的。優化器將經常能夠評估表達式一次並重用結果,但這並不能保證,並且通常需要專家分析來確定。
使用臨時表強制實現通常是最強大的解決方案,因為它保證了特定的評估順序和數量。