多语句表值函数与内联表值函数区别?

有几个例子要展示,以防万一:

内联表值

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

多语句表值

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

使用一种类型(内联语句或多语句)比另一种类型有优势吗?当其中一种比另一种更好时,是否存在某种特定的情景,还是仅仅是句法上的差异?我意识到这两个示例查询所做的事情不同,但我是否有理由这样写它们呢?

回答:

在内部,SQLServer处理内联表值函数就像对待视图一样,并且处理多语句表值函数的方式类似于存储过程。

当内联表值函数被用作外部查询的一部分时,查询处理器扩展UDF定义并生成访问底层对象的执行计划,使用这些对象上的索引。

对于多语句表值函数,为函数本身创建执行计划并存储在执行计划缓存中(一旦函数第一次执行)。如果多语句表值函数被用作较大查询的一部分,那么优化器就不知道函数返回了什么,因此做出了一些标准假设--实际上它假设函数将返回一个行。并且,函数的返回将通过对带有一行的表进行表扫描来访问。

当多语句表值函数返回大量行并在外部查询中被连接时,多语句表值函数的性能可能会很差。性能问题主要归因于这样一个事实:如果返回了一行,优化器将生成一个计划,这不一定是最合适的计划。

我们发现,由于这些潜在的性能问题,在可能的情况下,应该优先使用内联表值函数,而不是多语句函数(当UDF将用作外部查询的一部分时)。


参考:

https://cloud.tencent.com/developer/ask/28238


阅读更多 登录后自动展开
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页