And*_*ewC 188 sql t-sql sql-server user-defined-functions sql-server-2008
举几个例子,只是说:
内联表值
CREATE FUNCTION MyNS.GetUnshippedOrders()
RETURNS TABLE
AS
RETURN SELECT a.SaleId, a.CustomerID, b.Qty
FROM Sales.Sales a INNER JOIN Sales.SaleDetail b
ON a.SaleId = b.SaleId
INNER JOIN Production.Product c ON b.ProductID = c.ProductID
WHERE a.ShipDate IS NULL
GO
Run Code Online (Sandbox Code Playgroud)
多语句表值
CREATE FUNCTION MyNS.GetLastShipped(@CustomerID INT)
RETURNS @CustomerOrder TABLE
(SaleOrderID INT NOT NULL,
CustomerID INT NOT NULL,
OrderDate DATETIME NOT NULL,
OrderQty INT NOT NULL)
AS
BEGIN
DECLARE @MaxDate DATETIME
SELECT @MaxDate = MAX(OrderDate)
FROM Sales.SalesOrderHeader
WHERE CustomerID = @CustomerID
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 = @MaxDate
AND a.CustomerID = @CustomerID
RETURN
END
GO
Run Code Online (Sandbox Code Playgroud)
使用一种类型(在线或多语句)优于另一种类型是否有优势?当一个人比另一个人好或者纯粹是语法上的差异时,是否存在某些情况?我意识到这两个示例查询正在做不同的事情,但我有理由以这种方式编写它们吗?
阅读它们以及优点/差异尚未得到解释.
Tho*_*mas 136
在研究马特的评论时,我修改了我原来的陈述.他是正确的,即使它们都只是执行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
Run Code Online (Sandbox Code Playgroud)
在查询中,优化器将能够调用该函数一次并构建更好的执行计划,但它仍然不会比等效的,非参数化的ITVS或者更好VIEW.
在可行时,ITVF应优先于MSTVF,因为表中列的数据类型,可空性和排序规则,而您在多语句表值函数中声明这些属性,重要的是,您将从ITVF获得更好的执行计划.根据我的经验,我没有发现很多情况下ITVF比VIEW更好,但里程可能会有所不同.
感谢马特.
加成
自从我最近看到这个问题以来,Wayne Sheffield就是一个很好的分析,比较了内联表值函数和多语句函数之间的性能差异.
Pau*_*lin 27
在内部,SQL Server将内联表值函数视为视图,并将多语句表值函数视为与存储过程类似.
当内联表值函数用作外部查询的一部分时,查询处理器将扩展UDF定义并使用这些对象上的索引生成访问基础对象的执行计划.
对于多语句表值函数,为函数本身创建执行计划并将其存储在执行计划缓存中(一旦第一次执行该函数).如果多语句表值函数被用作较大查询的一部分,则优化器不知道函数返回什么,因此做出一些标准假设 - 实际上它假设函数将返回单行,并且返回通过对具有单行的表使用表扫描来访问该函数.
多语句表值函数表现不佳的情况是,它们返回大量行并在外部查询中连接.性能问题主要取决于优化器将生成一个假定返回单行的计划,这不一定是最合适的计划.
作为一般经验法则,我们发现,由于这些潜在的性能问题,应该使用内联表值函数而不是多语句函数(当UDF将用作外部查询的一部分时).