【问题标题】:SQL-Server Performance: What is faster, a stored procedure or a view?SQL-Server 性能:存储过程或视图哪个更快?
【发布时间】:2010-12-08 21:34:18
【问题描述】:

在 SQL Server 2005/2008 中,存储过程或视图哪个更快?

编辑: 正如你们中的许多人所指出的,我说得太含糊了。让我尝试更具体一点。
我想知道视图中的特定查询与存储过程中完全相同的查询的性能差异。 (我仍然很欣赏所有指出他们不同能力的答案)

【问题讨论】:

  • 但它们有重叠的用例。大概他在谈论那些案件。
  • @mjv 的回答非常好,但是,任何人都可以制定(参考)一个体面的基准来确认这一点吗?

标签: sql sql-server stored-procedures views


【解决方案1】:

存储过程 (SP) 和 SQL 视图是不同的“野兽”,如本文多次所述。

如果我们排除一些与查询计划缓存相关的[通常是次要的,除了边缘情况]性能考虑、与绑定到存储过程相关的时间等,这两种方法在整体上是等效的, 性能方面。 但是...

视图仅限于可以在单个 SELECT 语句中表达的任何内容(嗯,可能使用 CTE 和一些其他技巧),但总的来说,视图与查询的声明性形式相关 .另一方面,存储过程可以使用各种过程类型构造(以及声明性构造),因此,使用 SP,人们可以手工制作一种解决给定查询的方法这可能比 SQL-Server 的查询优化器所做的更有效(基于单个声明性查询)。在这些情况下,SP 可能要快得多(但要注意……优化器非常聪明,不需要太多就能使 SP 比等效视图慢得多。)

除了这些性能方面的考虑之外,SP 更通用,并且允许比视图更广泛的查询和操作。

【讨论】:

  • 我刚刚在一个已从视图更改为存储过程的 Crystal Report 上遇到了这个问题。 SP 明显较慢。几分钟,而不是几秒钟的视图。该报告有几个参数可供过滤。使用 SP,将返回 SELECT 语句的所有结果,然后进行过滤。在视图中,过滤条件似乎是动态添加的。您可以通过添加参数并在 WHERE 子句中使用它们来对 SP 执行相同的操作。但不要只是从视图中复制 SELECT 语句,将其放入 SP 并期望得到相同的结果。
【解决方案2】:

不幸的是,它们不是同一种野兽。

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

视图是数据的表示。它主要用作一个或多个具有基础连接的表的抽象。它始终是零、一或多行的结果集。

我怀疑你的问题更像是:

哪个更快:视图中的SELECTing,或存储过程中等效的SELECT 语句,假设相同的基表使用相同的 where 子句执行连接?

【讨论】:

  • 大概,他说的是返回零、一或多行结果集的 SP。
【解决方案3】:

这不是一个真正可以回答的问题,因为答案在所有情况下都适用。但是,作为 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 性能的所有方法,那么上面的第二个链接是一个不错的起点。

【讨论】:

  • 记住你所说的,像将所有视图转换为存储过程这样疯狂的事情会有好处吗??
  • 我不这么认为。风景也有一席之地。我不会过火。我不会将存储过程作为提高性能的第一站。我首先要确保我的索引是正确的。我可能错了,但在决定创建存储过程时,我通常不会考虑性能。通常我只是根据不受信任的用户输入处理查询,出于安全原因,我使用存储过程而不是满足的 SQL 语句。
【解决方案4】:

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

但您不能在选择或连接查询中使用存储过程的结果。

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

本论坛和其他地方的人们提到了其余的细节和差异。

【讨论】:

    【解决方案5】:

    我更喜欢存储过程,因为它允许更好地控制数据,如果你想构建一个好的、安全的模块化系统然后使用存储过程,它可以运行多个 sql 命令,具有控制流语句并接受参数。您可以在视图中执行的所有操作都可以在存储过程中执行。但在存储过程中,您可以灵活得多。

    【讨论】:

    • +1。推理是题外话,但我同意你所说的。
    【解决方案6】:

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

    我想我说的不是 sp 与视图,而是 sp 和视图 :)

    【讨论】:

    • 但我更关心性能而不是松散耦合。 (我使用 nHibernate 进行松散耦合。)但是从视图中选择的存储过程不会损害性能吗??
    【解决方案7】:

    存储过程和视图是不同的,有不同的用途。我将视图视为预设查询。我将存储过程视为代码模块。

    例如,假设您有一个名为 tblEmployees 的表,其中包含以下两列(以及其他列):DateOfBirthMaleFemale

    一个名为viewEmployeesMale 的视图仅过滤掉男性员工可能非常有用。一个名为viewEmployeesFemale 的视图也非常有用。这两种观点都是自我描述的,非常直观。

    现在,假设您需要生成一个年龄在 25 到 30 岁之间的所有男性员工的列表。我倾向于创建一个存储过程来生成这个结果。虽然它肯定可以构建为视图,但在我看来,存储过程更适合处理这个问题。日期操作尤其是在 null 是一个因素的情况下可能会变得非常棘手。

    【讨论】:

    • 感谢您的回答。我理解两者的区别,但你没有谈论性能影响,这是我更感兴趣的。你在你的例子中说你会使用 SP,因为日期操作很棘手,但你没有说关于性能的任何事情。您是说 SP 在您的场景中会更快吗?
    • 我真的不知道哪个会更快。您可能需要询问了解数据库内部结构的人。
    • 如果它是一种观点,那么一种策略如何更适合某事。你的测试在哪里。在性能方面,您描述的视图和过程基本上将得到相同的处理。
    【解决方案8】:

    我知道我不应该把它变成“讨论”,但我对此很感兴趣,只是想分享我对特定情况的经验观察,特别是上面所有的 cmets这表明从存储过程和视图中执行的等效 SELECT 语句应该具有大致相同的性能。

    我在数据库“A”中有一个视图,它将 5 个表连接到一个单独的数据库(db“B”)中。如果我在 SSMS 中附加到 db "A" 并从视图中选择 *,则返回 250000 行需要 >3 分钟。如果我从视图的设计页面中获取 select 语句并直接在 SSMS 中执行,则需要

    没有对绝对性能进行任何观察(db "B" 是一个我们不允许接触的 AX 数据库!),我仍然绝对相信在这种情况下,使用 SP 比使用 SP 快一个数量级一个视图来检索相同的数据,这适用于这种特殊情况下的许多其他类似的视图。

    我不认为这与创建与另一个数据库的连接有任何关系,除非通过使用视图,它以某种方式永远无法缓存连接,而选择却可以,因为我可以在两者之间切换2 在同一个 SSMS 窗口中重复选择,每次查询的性能保持一致。此外,如果我直接连接到 db "B" 并在没有 dbname.dbo.... refs 的情况下运行选择,则需要相同的时间。

    有什么想法吗?

    【讨论】:

      【解决方案9】:

      观看次数:

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

      存储过程:

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

      【讨论】:

        【解决方案10】:

        其他一些注意事项:虽然 SP 和视图之间的性能基本相同(假设它们执行完全相同的选择),但 SP 为您提供了相同查询的更大灵活性。

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

        【讨论】:

          【解决方案11】:

          找到详细的性能分析:https://www.scarydba.com/2016/11/01/stored-procedures-not-faster-views/

          编译时间比较:

          视图本身和存储过程之间的编译时间存在差异(它们几乎相同)。让我们看看几千次执行的性能:

          查看平均值:210.431431431431

          带有视图的存储过程 AVG:190.641641641642

          存储过程 AVG:200.171171171171

          这是以微发送来衡量的,因此我们看到的变化可能只是 I/O、CPU 或其他方面的一些差异,因为差异在 10mc 或 5% 时微不足道。

          包括编译时间在内的执行时间呢,因为有一个 区别:

          查询时长查看 AVG:10089.3226452906

          存储过程 AVG:9314.38877755511

          带有视图的存储过程 AVG:9938.05410821643

          结论

          除了编译时间的差异之外,我们看到视图实际上与存储过程执行完全相同,如果所讨论的查询是相同的。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-04-18
            • 1970-01-01
            • 1970-01-01
            • 2014-01-12
            • 2011-04-12
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多