3 回答

TA貢獻2065條經(jīng)驗 獲得超14個贊
在研究Matt的評論時,我修改了原始聲明。他是正確的,即使直接執(zhí)行SELECT語句,內(nèi)聯(lián)表值函數(shù)(ITVF)和多語句表值函數(shù)(MSTVF)的性能也會有所不同。SQL Server會將ITVF視為VIEW因為它將使用有關(guān)表的最新統(tǒng)計信息來計算執(zhí)行計劃。MSTVF等效于將SELECT語句的全部內(nèi)容填充到一個表變量中,然后再加入該變量中。因此,編譯器不能在MSTVF中的表上使用任何表統(tǒng)計信息。因此,在所有條件都相同的情況下(很少有),ITVF的性能將比MSTVF好。在我的測試中,完成時間的性能差異可以忽略不計,但是從統(tǒng)計角度來看,這是顯而易見的。
就您而言,這兩個功能在功能上并不相同。每次調(diào)用時,MSTV函數(shù)都會執(zhí)行一個額外的查詢,最重要的是,對客戶ID進行過濾。在大型查詢中,優(yōu)化器將無法利用其他類型的聯(lián)接,因為它需要為傳遞的每個customerId調(diào)用函數(shù)。但是,如果您重新編寫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
在查詢中,優(yōu)化器將能夠調(diào)用該函數(shù)一次并建立更好的執(zhí)行計劃,但是它仍然不會比等效的非參數(shù)化ITVS或a更好VIEW。
在可行的情況下,應(yīng)首選ITVF而不是MSTVF,因為表中各列的數(shù)據(jù)類型,可為空性和排序規(guī)則,而在多語句表值函數(shù)中聲明這些屬性,重要的是,您將從ITVF獲得更好的執(zhí)行計劃。根據(jù)我的經(jīng)驗,我沒有發(fā)現(xiàn)很多情況下ITVF比VIEW更好,但是里程可能會有所不同。

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

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