存储过程(Stored Procedures,SPs)与SQL视图是不同的“动物”,正如本文中多次提到的。
如果我们排除一些[通常是小问题,除了极端情况]与查询计划缓存、绑定到存储过程等相关的性能考虑因素,就整体而言,这两种方法在性能方面是等价的。 然而...
一个视图仅限于可以在单个SELECT语句中表达的内容(也可能包含CTE和其他技巧),但一般来说,视图限制在声明式的查询形式上。而存储过程则可以使用各种过程类型结构(以及声明式的结构),因此,使用SPs,可以手工制定解决给定查询的方式,这可能比SQL Server的查询优化器所做的更有效率(基于单个声明式查询)。 在这些情况下,SPs可能更快(但请注意...优化器非常聪明,很容易使SP比等效的视图慢得多。)
除了这些性能方面的考虑外,SPs更为多才多艺,允许进行更广泛的查询和操作。
很遗憾,它们不是同一种类型的东西。
存储过程是一组T-SQL语句,并且可以返回数据。它可以执行各种逻辑,并不一定返回结果集中的数据。
视图是数据的表示。它通常用作一个或多个表的抽象,具有底层连接。它始终是零行、一行或多行的结果集。
我怀疑您的问题更多的是这样:
在相同的基本表执行连接并使用相同的where子句时,从一个视图中进行
SELECT
,还是在存储过程中使用等效的SELECT
语句更快?
这并不是一个可以一概而论的问题。然而,对于SQL Server的具体实现来说,一般情况下存储过程比直接SQL语句更快,因为在第一次保存和执行存储过程时,服务器会进行各种优化。
视图本质上是一个保存的SQL语句。
因此,我认为一般情况下,如果每个SQL语句相同,并且SQL语句可以从优化中受益,则存储过程很可能比视图快。否则,一般情况下它们的性能类似。
参考这些链接文档支持我的答案:
http://www.sql-server-performance.com/tips/stored_procedures_p1.aspx
http://msdn.microsoft.com/en-us/library/ms998577.aspx
此外,如果你正在寻找优化SQL Server性能的所有方法,上面第二个链接是一个很好的起点。
简而言之,根据我在一些复杂查询中的经验,存储过程比函数更具性能优势。
但是你不能在select或join查询中使用存储过程的结果。
如果您不想在另一个查询中使用结果集,则最好使用SP。
其余的细节和差异由本论坛和其他地方的人员提供。
我更喜欢存储过程,因为它可以更好地控制数据。如果你想要构建一个良好、安全、模块化的系统,那么请使用存储过程,它可以运行多个SQL命令,具有流程控制语句和接受参数的能力。在视图中所能做的一切都可以在存储过程中完成,但是在存储过程中,你可以以更大的灵活性进行操作。
我认为另一种思考方式是使用存储过程来选择视图。这将使您的架构成为一个松散耦合的系统。如果您决定在未来更改模式,您就不必太担心它会破坏前端。
我的意思是,与其考虑存储过程与视图之间的区别,不如同时考虑存储过程和视图 :)
tblEmployees
的表格,其中包括这两个列(以及其他列):DateOfBirth
和MaleFemale
。viewEmployeesMale
的视图只过滤出男性员工,非常有用。另一个名为viewEmployeesFemale
的视图也非常有用。这两个视图都是自描述且非常直观。我知道不应该把这变成一个“讨论”,但我对此非常感兴趣,想分享一下我针对特定情况的经验观察,特别是针对以上所有评论的参考,这些评论指出,从存储过程和视图中执行等效的SELECT语句应该具有大致相同的性能。
我在数据库“A”中有一个视图,它连接了另一个数据库(db“B”)中的5个表。如果我在SSMS中连接到db“A”并从视图中选择*,则需要> 3分钟才能返回250000行。如果我从视图的设计页面中获取select语句,并直接在SSMS中执行它,则只需<25秒。将相同的select语句放入存储过程中,在执行该过程时具有相同的性能。
不对绝对性能进行任何观察(db“B”是一个我们不允许触及的AX数据库!),但我仍然坚信,在这种情况下,使用SP比使用视图检索相同数据快上一个数量级,而且在许多其他类似视图的情况下也适用。
我认为这与创建到其他数据库的连接无关,除非使用视图会导致无法缓存连接,而使用SELECT则可以,因为我可以在同一个SSMS窗口中反复切换这两个SELECT,并且每个查询的性能保持一致。此外,如果直接连接到“B”数据库并在没有dbname.dbo...引用的情况下运行SELECT,则需要相同的时间。 有任何想法吗?视图:
存储过程:
还有一些其他的考虑因素:虽然存储过程(SP)和视图(view)之间的性能基本相同(假设它们执行完全相同的选择),但是SP为相同的查询提供了更多的灵活性。
SELECT * FROM view
来调用它;即,在视图中编译的选择上进行选择。