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

12 浏览
0 Comments

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

我一直在阅读有关执行计划和存储过程中动态参数问题的相关内容,我知道了解决方案。然而,我所阅读的所有内容都表明SQL Server会对存储过程缓存执行计划,但没有提到表值函数。我想知道每次调用表值函数时是否会重新编译?什么时候最好使用表值函数而不是存储过程?

0
0 Comments

SQL Server中的表值函数和存储过程是两种不同的数据库对象,它们在使用和执行计划缓存方面存在一些差异。表值函数可以返回单个结果,而存储过程可以返回一个或多个结果,也可以不返回结果。

首先,有人认为函数的执行计划也会被缓存,但这还没有经过验证。因为函数的执行计划是可以被缓存的,所以没有理由认为函数的执行计划不能被缓存。

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

另外,一个值得注意的问题是,函数无法添加"OPTIMIZE FOR UNKNOWN"选项,这使我认为该选项对函数无效。

选择使用函数还是存储过程取决于所需的结果。如果需要返回单个结果,则可以使用表值函数;如果需要返回一个或多个结果,或者根本不需要返回结果,则可以使用存储过程。

0
0 Comments

SQL Server: Table-valued Functions vs. Stored Procedures

在SQL Server中,我们可以使用表值函数(Table-valued Functions)和存储过程(Stored Procedures)来查询数据。这两种方法各有优劣,本文将讨论它们的差异以及使用场景。

表值函数(TVFs)提供了一种类似宏的功能,即在外部查询中展开。它没有自己的执行计划,而是依赖于调用它的查询的执行计划。因此,对于内联表值函数(Inline TVFs),优化器会结合外部查询的选择列表和条件进行优化。而对于多语句表值函数(Multi-statement TVFs),由于必须先执行完所有语句,再进行过滤,所以优化是不太可能的。

相比之下,存储过程更加灵活。存储过程可以使用提示(Hints)来指定查询的执行计划、更改状态(如SET NOCOUNT ON、SET XACTABORT)等。此外,存储过程还可以缓存执行计划,因此在查询数据时效率更高,甚至比视图(Views)还要高。

对于客户端代码,我个人更倾向于使用存储过程而不是内联表值函数。因为内联表值函数无法使用SET语句来更改状态,而在客户端代码中,有时候我们需要对状态进行控制。

有人可能会问,既然存储过程和多语句表值函数都可以返回多行结果集,为什么还要使用内联表值函数呢?原因在于,内联表值函数的执行计划会根据外部查询的条件进行优化,而存储过程的执行计划则是固定的。所以,如果需要根据参数化输入来动态选择查询结果的列,内联表值函数是更好的选择。

还有一个问题是关于执行计划缓存的。存储过程可以缓存执行计划,而内联表值函数也可以缓存。但是,内联表值函数无法使用"OPTION OPTIMIZE FOR ? UNKNOWN"语句来指定执行计划。这是否意味着内联表值函数的执行计划将和存储过程一样,第一次执行时会被缓存下来,以后的调用都会使用这个原始的执行计划呢?或者SQL Server只会缓存一个通用的执行计划,不考虑参数的影响呢?

对于这个问题,我们可以将"OPTION OPTIMIZE FOR ? UNKNOWN"语句放在使用内联表值函数的外部查询中(同样适用于大多数提示)。无论是存储过程、临时批处理还是使用内联表值函数的视图,它们都会被缓存执行计划。至于标量函数(Scalar Functions),如果它涉及表访问,则与多语句表值函数类似,性能较差。

总结一下,无论是表值函数还是存储过程,都可以缓存执行计划。但是为了获得更好的性能,我们应该避免使用多语句表值函数,并在适当的地方使用提示。对于返回表的情况,内联表值函数是性能更好的选择。而存储过程则更加灵活,可以通过使用提示和更改状态来优化查询。

0