Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 现在使用T-SQL中的UDF安全吗?_Sql Server_Tsql_User Defined Functions_Sql Execution Plan - Fatal编程技术网

Sql server 现在使用T-SQL中的UDF安全吗?

Sql server 现在使用T-SQL中的UDF安全吗?,sql-server,tsql,user-defined-functions,sql-execution-plan,Sql Server,Tsql,User Defined Functions,Sql Execution Plan,14年来,我一直遵循着一条誓言:“在受影响的一行或两行以上不要使用UDF。” 我将通过一个非常基本的例子,与我的团队分享UDF有多糟糕: /* CREATE FUNCTION dbo.Test (@Numerator Float, @Denominator Float) RETURNS Float AS BEGIN DECLARE @Return Float; SET @Return = @Numerator / NullIf(@Denominator,0); RETURN @Return EN

14年来,我一直遵循着一条誓言:“在受影响的一行或两行以上不要使用UDF。”

我将通过一个非常基本的例子,与我的团队分享UDF有多糟糕:

/*
CREATE FUNCTION dbo.Test (@Numerator Float, @Denominator Float)
RETURNS Float AS
BEGIN
DECLARE @Return Float;
SET @Return = @Numerator / NullIf(@Denominator,0);
RETURN @Return
END
GO
*/
----------------------------------------------------------------------
SELECT rn / NullIf(3.00,0)
FROM
       (
       SELECT TOP 1000000 rn = Convert(Float,ROW_NUMBER() OVER (ORDER BY s1.[object_id]))
       FROM sys.all_objects AS s1 CROSS JOIN sys.all_objects AS s2
       ORDER BY s1.[object_id]
       ) tbl;
----------------------------------------------------------------------
SELECT dbo.Test (rn,3.00)
FROM
       (
       SELECT TOP 1000000 rn = Convert(Float,ROW_NUMBER() OVER (ORDER BY s1.[object_id]))
       FROM sys.all_objects AS s1 CROSS JOIN sys.all_objects AS s2
       ORDER BY s1.[object_id]
       ) tbl;
----------------------------------------------------------------------
--DROP FUNCTION dbo.Test;
GO
然而,当我准备做show-n-tell时,运行第一个区块和第二个区块所需的时间几乎完全相同,大约为8秒。我记得大约6年前运行了一个非常类似的实验,并注意到执行时间的指数差异

UDF现在可以安全使用了吗?发生了什么变化?

如果“安全”的意思是“不慢和/或效率低”,那么答案是: Inline=good,not Inline=bad.不要把我的工作当回事,问问微软:

当编写得不好时,T-SQL内联函数的速度可能会很慢,但T-SQL标量UDF和多语句表值函数(mTVF)肯定会破坏性能

这里有几个链接,我把一些测试放在一起,或者更详细地讨论这个问题


现在,SQL Server 2019引入了内联标量和mTVFs。这些都比他们的前辈好,但并不完美。例如,使用标量UDF作为检查约束或计算列将迫使优化器选择一个序列计划,其中包含引用该表的查询(insert/update/delete和SELECTs)。即使在查询中未调用引用函数的列时也是如此。在SQL 2019中仍然如此

UDF不是邪恶的。与所有代码一样,它们可能写得很差,或者不是最佳的方式。例如,可以将UDF缩减为一个>>>RETURN@Numerator/NullIf(@deminator,0)时,您的UDF有多个语句,就像所有工具一样,它们有优点和缺点。但与SQL的所有内容一样,性能完全是根据情况而定的。在
where
子句中避免它们可能是一个有效的规则,但是您是否希望在多个位置重复SQL,并冒着忘记更新其中一个SQL的风险。在许多情况下,一个UDF可以被一个ITVF代替,它没有典型的UDF性能差,因为它像一个视图一样插入内联。我知道有一条语句只是直接“返回”,因为这是我的第一个方法。当它快速返回时,我夸大了它以模仿大多数其他UDF,最基本的UDF。它仍然返回得很快,因此,我决定发布更复杂的版本,以进一步证明简单UDF的性能有了显著提高(或者,…也许我的内存真的很差)。我相信SQL Server的每个部分在14年后都会表现得更好:)@AlanBurstein我的断言成立。正确使用时,每个工具都有价值。首先,我怀疑大多数理性的人永远不会使用UDF作为挑战,如果他们这样做了,他们会很快意识到这是一个愚蠢的想法。第二,绩效很重要,但不是一切。数据完整性、可管理性、可用性。。。也应予以考虑。例如,UDF可以通过减少接触点来提高一致性。客户增加了风险评级。他们花费了数千工时来识别、调整和验证无数遗留报告和流程。我有一个接触点。我记得在某个地方读到,内联函数有更好的性能,因为查询优化器可以像使用它们的代码的一部分一样使用它们,这意味着优化过程是在实际运行的整个代码上完成的,但非内联函数不是这样。我喜欢奥威尔式的引用,但这不是我投票的唯一原因。