【问题标题】:Would it negatively affect performance writing "WHERE" on returned resultset from Table-Val. Function rather than on query itself?是否会对从 Table-Val 返回的结果集写入“WHERE”的性能产生负面影响。函数而不是查询本身?
【发布时间】:2020-06-14 11:54:06
【问题描述】:

我有一个 SQL 查询,其中当前使用表值函数返回结果集,如下所示:

CREATE FUNCTION [dbo].[fnGetUserTable]
RETURNS @tblUser TABLE (
UserDeviceId BIGINT,
UserDeviceName NVARCHAR(50),
UserName NVARCHAR(50)
)

AS
BEGIN
INSERT INTO @tblUser 
Select Device.DeviceId, Device.DeviceName, User.UserName
FROM Device INNER JOIN User ON Device.DeviceId = User.UserDeviceId
RETURN
END

但是,我从函数中过滤返回的结果集,如下所示:

SELECT UserDeviceId, UserDeviceName, UserName
FROM [dbo].[fnGetUserTable]
WHERE UserName ='myuser@users.com'

假设表 User 中有 1000,000 条记录,从性能方面来说,最好的做法是按照前面的示例过滤函数返回的结果集, 或将 where 条件直接添加到 [dbo].[fnGetGoldRateTable] 函数内的 SQL 查询中,如下所示:

CREATE FUNCTION [dbo].[fnGetUserTable]
RETURNS @tblUser TABLE (
UserDeviceId BIGINT,
UserDeviceName NVARCHAR(50),
UserName NVARCHAR(50)
)

AS
BEGIN
INSERT INTO @tblUser 
Select Device.DeviceId, Device.DeviceName, User.UserName
FROM Device INNER JOIN User ON Device.DeviceId = User.UserDeviceId
WHERE UserName ='myuser@users.com'
RETURN
END

或者它是否会产生相同的性能影响,因为 SQL Server 在 Select 查询中在 Where 子句之前处理 From 子句,这意味着从函数查询返回的结果集将由 SQL Server 插入到 Temp 表中然后过滤根据添加的 where 条件,如果在函数本身中添加 Where 条件,会导致相同的性能标准??

请指教,

提前致谢,

【问题讨论】:

  • 为什么这是一个函数而不是一个视图?
  • @David Browne - Microsoft,基本上我将参数传递给它,例如“@LangId”,因此查询应返回本地化值,这就是为什么它是一个函数,这只是一个示例代码,因为原始查询加入3个表并基本返回结果
  • 你比较过这两个选项的查询计划吗?

标签: sql-server performance user-defined-functions


【解决方案1】:

了解的一种方法是通过运行每种方法来比较两种方法,并查看每种方法的执行计划,找出哪种方法成本更低且成本有效。

这里是启用执行计划的参考

https://docs.microsoft.com/en-us/sql/relational-databases/performance/display-an-actual-execution-plan?view=sql-server-ver15

【讨论】:

    【解决方案2】:

    从性能方面来说,最好的做法是按照前面的示例过滤函数返回的结果集,或者将 where 条件直接添加到 SQL 查询中

    在这种特殊情况下,在函数中添加谓词显然更好,因为它可以在列上使用索引。

    但那是因为这是一个多语句表值函数,并且对于查询优化器 (QO) 来说是“不透明的”。执行函数内部的逻辑并将结果返回给外部查询。如果这是一个内联表值函数,情况会有所不同。看起来像这样:

    CREATE FUNCTION [dbo].[fnGetUserTable] ()
    RETURNS TABLE 
    as
    RETURN
        Select Device.DeviceId, Device.DeviceName, User.UserName
        FROM Device INNER JOIN [User] ON Device.DeviceId = User.UserDeviceId
    

    并且一个Inline Table-Valued Function被解析并折叠到外部查询的查询计划中,QO可以优化整个事情。特别是它可以将查询谓词从外部查询“下推”到函数中。

    之所以青睐内联表值函数,正是因为在按函数的返回列之一进行过滤时,您不必添加函数参数即可获得高效的查询性能。

    【讨论】:

    • 感谢您的回复,因为这有足够的信息,但是我有以下查询,首先在我上面的示例中创建的函数是否被视为内联表值函数?就像我一样,因为它返回一个表,它已经是一个内联表值函数?其次,我是否清楚地理解,对于内联表值函数,我不必将“where 条件条件”作为参数传递给函数,只需将这些条件添加到外部查询就足够了,并且不会对性能产生负面影响? ?感谢您的帮助
    • 您的函数不是内联 TVF,因为它声明了返回表并插入其中。如果 TVF 实际上只有一个语句并不重要,它仍然不是内联 TVF。是的,使用内联 TVF,您通常可以在外部查询中应用谓词并让 QO 找出答案。
    猜你喜欢
    • 2010-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-29
    相关资源
    最近更新 更多