3 回答

TA貢獻1909條經驗 獲得超7個贊
在研究Matt的評論時,我修改了原始聲明。他是正確的,即使直接執行SELECT語句,內聯表值函數(ITVF)和多語句表值函數(MSTVF)的性能也會有所不同。SQL Server會將ITVF視為VIEW因為它將使用有關表的最新統計信息來計算執行計劃。MSTVF等效于將SELECT語句的全部內容填充到一個表變量中,然后再加入該變量中。因此,編譯器不能在MSTVF中的表上使用任何表統計信息。因此,在所有條件都相同的情況下(很少有),ITVF的性能將比MSTVF好。在我的測試中,完成時間的性能差異可以忽略不計,但是從統計角度來看,這是顯而易見的。
就您而言,這兩個功能在功能上并不相同。每次調用時,MSTV函數都會執行一個額外的查詢,最重要的是,對客戶ID進行過濾。在大型查詢中,優化器將無法利用其他類型的聯接,因為它需要為傳遞的每個customerId調用函數。但是,如果您重新編寫MSTV功能,如下所示:
CREATE FUNCTION MyNS.GetLastShipped()
RETURNS @CustomerOrder TABLE
(
SaleOrderID INT NOT NULL,
CustomerID INT NOT NULL,
OrderDate DATETIME NOT NULL,
OrderQty INT NOT NULL
)
AS
BEGIN
INSERT @CustomerOrder
SELECT a.SalesOrderID, a.CustomerID, a.OrderDate, b.OrderQty
FROM Sales.SalesOrderHeader a
INNER JOIN Sales.SalesOrderHeader b
ON a.SalesOrderID = b.SalesOrderID
INNER JOIN Production.Product c
ON b.ProductID = c.ProductID
WHERE a.OrderDate = (
Select Max(SH1.OrderDate)
FROM Sales.SalesOrderHeader As SH1
WHERE SH1.CustomerID = A.CustomerId
)
RETURN
END
GO
在查詢中,優化器將能夠調用該函數一次并建立更好的執行計劃,但是它仍然不會比等效的非參數化ITVS或a更好VIEW。
在可行的情況下,應首選ITVF而不是MSTVF,因為表中各列的數據類型,可為空性和排序規則,而在多語句表值函數中聲明這些屬性,重要的是,您將從ITVF獲得更好的執行計劃。根據我的經驗,我沒有發現很多情況下ITVF比VIEW更好,但是里程可能會有所不同。

TA貢獻1780條經驗 獲得超4個贊
在內部,SQL Server像對待視圖一樣對待內聯表值函數,并像對待存儲過程一樣對待多語句表值函數。
當將內聯表值函數用作外部查詢的一部分時,查詢處理器將擴展UDF定義并使用這些對象上的索引生成訪問基礎對象的執行計劃。
對于多語句表值函數,將為函數本身創建執行計劃,并將其存儲在執行計劃緩存中(一旦第一次執行該功能)。如果將多語句表值函數用作較大查詢的一部分,則優化器不知道該函數返回什么,因此做出一些標準假設-實際上,它假設該函數將返回一行,并且該函數的返回通過對具有一行的表進行表掃描來訪問該功能。
多語句表值函數的性能較差的地方是它們返回大量行并在外部查詢中聯接時。性能問題主要歸結于以下事實:優化器將假設返回一行而生成一個計劃,這不一定是最合適的計劃。
作為一般經驗法則,我們發現由于這些潛在的性能問題,在可能的情況下,應優先使用內聯表值函數而不是多語句函數(當將UDF用作外部查詢的一部分時)。

TA貢獻1772條經驗 獲得超5個贊
我認為您的示例很好地回答了這個問題。第一個功能可以單選完成,這是使用內聯樣式的一個很好的理由。第二個可能是作為單個語句完成的(使用子查詢來獲取最大日期),但是某些編碼人員可能會發現您更容易閱讀或更自然地在多個語句中執行此操作。某些簡單的功能無法在一個語句中完成,因此需要多語句版本。
我建議盡可能使用最簡單的(內聯)語句,必要時(顯然)或在個人喜好/可讀性使其成為多余打字內容時使用多語句。
- 3 回答
- 0 關注
- 600 瀏覽
添加回答
舉報