Sql-Server

UDF 和內置函式行為

  • April 29, 2022

進行以下查詢:

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,我發現它在大型數據集上表現更好。但是,我仍然無法找到以下問題的明確答案:

  1. 查詢分析器會將 aUserDefinedScalarFunction(4) 優化為 ScalarValue 還是針對每條記錄進行評估?
  2. INNER JOIN dbo.aUserDefineTableFunction(@X) 會在臨時表中實現一次,還是會為每條記錄執行?該函式返回表(不是表變數)。
  3. SELECT 的結果是否

$$ value $$FROM STRING_SPLIT(@X,’,’) 得到優化還是針對每次比較進行評估? 4. SELECT Value FROM dbo.MySplitterFunction(@X) 的結果是否得到優化或在每次比較期間進行評估?

  1. 這取決於功能。對於使用schemabinding指定的**確定性函式,優化器通常只能評估其結果一次,並記憶體答案。

有關詳細資訊,請參閱:

  1. 內聯表值函式在優化之前擴展為呼叫查詢文本,因此沒有特殊機會進行早期評估和記憶體。這並不意味著執行計劃不會包含任何記憶體和重用優化。在適用的情況下,優化器將考慮那些(例如假離線),就像它對沒有內聯函式的查詢一樣。
  2. 通常,優化器將能夠判斷SPLIT_STRING在恆定輸入上返回確定性結果。該計劃可能只評估一次拆分,但這確實取決於計劃的形狀。
  3. 假設 splitter 函式是一個多語句表值函式,那麼結果很可能只求值一次。有關詳細資訊,以及如何判斷執行計劃中是否發生記憶體,請參閱:

綜上所述,你對這一切保持謹慎是對的。優化器將經常能夠評估表達式一次並重用結果,但這並不能保證,並且通常需要專家分析來確定。

使用臨時表強制實現通常是最強大的解決方案,因為它保證了特定的評估順序和數量。

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