SQL-Server性能:存储过程和视图哪个更快?

49
在SQL Server 2005/2008中,存储过程和视图哪个更快?编辑:如许多人所指出的那样,我的问题表述太笼统了。让我尝试更加具体一些。我想知道在视图中执行特定查询与在存储过程中执行完全相同的查询之间的性能差异。(我仍然感谢所有指出它们不同能力的答案)

7
但它们具有重叠的用例。据推测,他在谈论那些情况。 - recursive
3
@mjv的回答很好,但有没有人能提供一个可靠的基准来确认这一点? - Dennis Jaheruddin
11个回答

80

存储过程(Stored Procedures,SPs)与SQL视图是不同的“动物”,正如本文中多次提到的。

如果我们排除一些[通常是小问题,除了极端情况]与查询计划缓存、绑定到存储过程等相关的性能考虑因素,就整体而言,这两种方法在性能方面是等价的。 然而...

一个视图仅限于可以在单个SELECT语句中表达的内容(也可能包含CTE和其他技巧),但一般来说,视图限制在声明式的查询形式上。而存储过程则可以使用各种过程类型结构(以及声明式的结构),因此,使用SPs,可以手工制定解决给定查询的方式,这可能比SQL Server的查询优化器所做的更有效率(基于单个声明式查询)。 在这些情况下,SPs可能更快(但请注意...优化器非常聪明,很容易使SP比等效的视图慢得多。)

除了这些性能方面的考虑外,SPs更为多才多艺,允许进行更广泛的查询和操作。


1
我刚在一个Crystal Report上遇到了这个问题,该报表已从视图更改为存储过程。SP的速度明显变慢了。与视图相比,需要几分钟而不是几秒钟。报告有几个参数可用于筛选。使用SP时,所有SELECT语句的结果都将被返回,然后进行筛选。使用视图时,过滤条件似乎是动态添加的。您可以通过添加参数并在WHERE子句中使用它们来使用SP执行相同的操作。但是不要只是从视图中复制SELECT语句,将其放入SP并期望获得相同的结果。 - KevinD
你的回答来源是什么?能分享一下吗? - Kid

14

很遗憾,它们不是同一种类型的东西。

存储过程是一组T-SQL语句,并且可以返回数据。它可以执行各种逻辑,并不一定返回结果集中的数据。

视图是数据的表示。它通常用作一个或多个表的抽象,具有底层连接。它始终是零行、一行或多行的结果集。

我怀疑您的问题更多的是这样:

在相同的基本表执行连接并使用相同的where子句时,从一个视图中进行SELECT,还是在存储过程中使用等效的SELECT语句更快?


4
他可能在谈论返回零行、一行或多行结果集的存储过程。 - recursive

10

这并不是一个可以一概而论的问题。然而,对于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性能的所有方法,上面第二个链接是一个很好的起点。


考虑到你所说的,像将所有视图转换为存储过程这样疯狂的做法会有好处吗? - 7wp
我不这么认为。视图也有它的位置。我不会过度使用。我不会把存储过程作为提高性能的首选。我会先确保我的索引是正确的。我可能在这方面错了,但通常我不会考虑性能来决定是否创建存储过程。通常情况下,我只是基于不受信任的用户输入工作的查询,并出于安全原因使用存储过程而不是一个含有内容的SQL语句。 - David

5

简而言之,根据我在一些复杂查询中的经验,存储过程比函数更具性能优势。

但是你不能在select或join查询中使用存储过程的结果。

如果您不想在另一个查询中使用结果集,则最好使用SP。

其余的细节和差异由本论坛和其他地方的人员提供。


5

我更喜欢存储过程,因为它可以更好地控制数据。如果你想要构建一个良好、安全、模块化的系统,那么请使用存储过程,它可以运行多个SQL命令,具有流程控制语句和接受参数的能力。在视图中所能做的一切都可以在存储过程中完成,但是在存储过程中,你可以以更大的灵活性进行操作。


+1。推理有些离题,但我同意你说的话。 - David

4

我认为另一种思考方式是使用存储过程来选择视图。这将使您的架构成为一个松散耦合的系统。如果您决定在未来更改模式,您就不必太担心它会破坏前端。

我的意思是,与其考虑存储过程与视图之间的区别,不如同时考虑存储过程和视图 :)


2
但我更关心性能而不是松耦合。(我使用nHibernate进行松耦合。)但是,从视图中选择存储过程会影响性能吗? - 7wp

3
存储过程和视图是不同的,有不同的用途。我认为视图就像是预先定义好的查询,而存储过程则像是代码模块。
例如,假设您有一个名为tblEmployees的表格,其中包括这两个列(以及其他列):DateOfBirthMaleFemale
一个名为viewEmployeesMale的视图只过滤出男性员工,非常有用。另一个名为viewEmployeesFemale的视图也非常有用。这两个视图都是自描述且非常直观。
现在,假设您需要列出所有年龄在25岁至30岁之间的男性员工。我倾向于创建一个存储过程来生成这个结果。虽然它当然可以作为视图构建,但在我看来,存储过程更适合处理此类情况。特别是在涉及到空值的日期操作时,可能会变得非常棘手。

谢谢你的回答。我理解两者之间的区别,但你没有谈到性能方面的影响,这才是我更感兴趣的。你在例子中提到会使用存储过程,因为日期操作很棘手,但你没有提到性能方面的任何内容。你是说在你的情况下存储过程会更快吗? - 7wp
我不确定哪个更快。你可能需要询问一些了解数据库内部的人。 - Michael Riley - AKA Gunny
如果策略只是一种观点,怎么能更适合某件事呢?你的测试在哪里?就性能而言,你所描述的视图和过程基本上会得到相同的处理。 - Plixxer

1

我知道不应该把这变成一个“讨论”,但我对此非常感兴趣,想分享一下我针对特定情况的经验观察,特别是针对以上所有评论的参考,这些评论指出,从存储过程和视图中执行等效的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,则需要相同的时间。 有任何想法吗?

1

视图:

  • 我们可以在视图上创建索引(存储过程中不可能)
  • 将表数据的抽象视图(仅限多个表的有限列访问)轻松提供给其他DBA/用户

存储过程:

  • 我们可以向存储过程传递参数(视图中不可能)
  • 在存储过程中执行多个语句(如插入、更新、删除操作)

0

还有一些其他的考虑因素:虽然存储过程(SP)和视图(view)之间的性能基本相同(假设它们执行完全相同的选择),但是SP为相同的查询提供了更多的灵活性。

  • SP将支持对结果集进行排序;即,包括ORDER BY语句。在视图中无法这样做。
  • SP已经完全编译,只需要一个exec来调用它。视图仍然需要一个SELECT * FROM view来调用它;即,在视图中编译的选择上进行选择。

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