SQL Server:表值函数 vs 存储过程

38

我一直在阅读关于执行计划以及存储过程中动态参数问题的相关内容。我知道了解决这个问题的建议方案。

但是我的问题是,所有我所读到的资料都表明 SQL Server 会缓存存储过程的执行计划,但并没有提到表值函数。我猜想 SQL Server 也会为视图进行缓存(仅供参考)。

每次调用表值函数时,它是否需要重新编译?

与存储过程相比,何时最好使用表值函数?


可能是函数 vs 存储过程的重复问题。 - Gert Arnold
这个问题在3年前被提出并回答了。即使它被指称为重复,关闭它的目的是什么? - IamIC
2个回答

36

内联表值函数(TVF)类似于宏:它被扩展到外部查询中。它没有计划:调用SQL有一个计划。

多语句TVF有一个计划(将找到一个参考)。

当您希望为参数化输入变化SELECT列表时,TVF非常有用。内联TVF会被展开,外部select/where将被优化器考虑。对于多语句TVF来说,优化实际上是不可能的,因为它必须运行到完成,然后进行过滤。

个人而言,我会在多语句TVF上使用存储过程。它们更加灵活(例如提示、可以更改状态、SET NOCOUNT ON、SET XACTABORT等)。

我不反对内联TVF,但不倾向于在客户面向的代码中使用它们,因为无法使用SET和更改状态。


1
@IanC:视图也可以缓存(就像内联TVF一样)。但是存储过程更加灵活(例如,如果我想要SET NOCOUNT ON、SET XACTABORT + TRY/CATCH)。 - gbn
我正在使用多语句 TVF 用于各种参数化输入,并包含“OPTION (OPTIMIZE FOR (@JobID UNKNOWN....))”。这是最优的吗? - IamIC
1
@IanC:OPTION提示可能会被忽略。多语句TVF是臭名昭著的黑匣子:我不确定它是否会传播到TVF中。链接: - gbn
4
我们所说的黑匣子是指:你的tvf返回了20列。你使用SELECT col1,col2 from tvf WHERE foo = bar。一个内联TVF(或仅具有col1和col2的存储过程)将针对col1、col2与where来计划工作。而多列的TVF则必须运行所有20列,暂存结果,然后进行过滤,并限制为2列。 - gbn
1
@IanC: "OPTION OPTIMIZE FOR ? UNKNOWN"应该放在使用内联TVF的外部查询中(顺便说一下,这适用于大多数提示)。所有计划都是相等的,无论是存储过程还是临时批处理或使用内联TVF的视图。标量:如果标量函数进行表访问,则与多个TVF一样糟糕。它可能有一个计划,但我现在记不起来了 :-) - gbn
显示剩余8条评论

1

我还没有验证过这一点,但我认为函数的执行计划也会被缓存。我看不出为什么不可能。

视图的执行计划不会被缓存。视图中的查询将成为使用该视图的查询的一部分,因此可以为使用该视图的查询缓存执行计划,但不能为视图本身缓存执行计划。

使用函数还是存储过程取决于您需要从中获得什么结果。表值函数可以返回单个结果,而存储过程可以返回一个结果、多个结果或根本没有结果。


1
我注意到的一件事是,我无法将“OPTIMIZE FOR UNKNOWN”添加到函数中,这让我觉得它是无效的。 - IamIC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接