3 回答

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

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

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