【问题标题】:Stored Procedures - End of days存储过程 - 天数结束
【发布时间】:2008-10-24 01:00:23
【问题描述】:

我正在收听 Hanselminutes 播客; “StackOverflow 使用 ASP.NET MVC - Jeff Atwood 和他的技术团队”。在 Podcast 的过程中,他们谈到了 SQL 服务器,并说了一些类似于“存储过程的日子已经结束”的内容。

现在我不是 DBA,但这让我有点意外。我一直认为 SP 是追求速度(因为它们被遵守)和安全性的方式,更不用说可扩展性和可维护性了。如果情况并非如此,并且 SP 已处于最后阶段,那么将用什么替代它们或我们将来应该做什么?

【问题讨论】:

  • 那是一个很好的播客。将其作为评论发布,因为它无关紧要。
  • 播客链接:hanselman.com/blog/…

标签: sql-server stored-procedures


【解决方案1】:

也许我太老派了,或者太懒了,或者两者兼而有之,但我不得不不同意。存储过程一次又一次地“挽救了局面”,因为当出现较小的后端更改或错误时我们只需要修复存储过程,而不是在几十个桌面和网络上更新桌面应用程序服务器。此外,用户不会被打断。这节省了大量的精力和用户的麻烦。

此外,一些数据库操作只会在服务器上更高效,而不是在网络上来回进行,尤其是。当一个存储过程调用另一个存储过程调用另一个等时(有或没有游标)

编辑:在 SOA 架构中,更新客户端应用程序问题得到缓解(感谢 maud-dib),但存储过程相互调用仍然比到 SOA 层的多个网络往返更有效。而且更新 SOA 层也不是一件容易的事。

【讨论】:

  • 我同意,这对于任何类型的分布式应用程序都是如此。我确实觉得它不像以前对以服务器为中心的应用程序那么重要,因为在应用服务器中放置的重新编译的 DLL 执行相同的功能。
  • 应用程序不应连接到数据库。它们应该连接到服务层。
  • LOL - 我同意,除了 (a) 其中一些应用程序比 SOA 更早,(b) 其中一些应用程序是实时的,(c) SOA 只是解决了问题,因为最初的断言是存储过程是“过时的”
  • "应用程序不应该连接数据库。应该连接到服务层应用程序。"
  • @[anonymousstackoverflowuser]:嗯,是的,对。往上看。因为现在绝对所有东西都需要至少三层,包括遗留系统。不是。 ;-)
【解决方案2】:

在现代系统上,参数化查询在服务器上进行编译和缓存,因此它们与存储过程一样快。它们也具有大部分相同的安全功能。

对于服务于单个应用程序的数据库,将查询逻辑放在代码中的相关位置会更有意义。如果不出意外,它可以更轻松地进行源代码控制。如果您在服务器上保留存储过程,跟踪它们很快就会变得一团糟。此外,如果您使用的是 ORM 工具,那么您可能没有太多真正的 SQL 方式。

如果您的数据库服务于多个不同的应用程序,那么您可能仍希望使用存储过程来执行应用程序之间的业务规则。

【讨论】:

  • 当您拥有多种语言的多个应用程序(因此无法在它们之间共享代码)时,同意 SP 是一种祝福。
  • 但是谁编写了一个存储过程只执行查询的系统?你为更新做什么 - 或更新副作用(没有触发器,当然仍然很烂;-))
  • “查询”也指插入、更新、删除等。
  • 如果您的数据库服务于多个应用程序,那么您可能需要一个服务 (WS/REST) 层。
  • @[maud-dib.blogspot.com]:如果数据库只为一个应用程序提供服务,则对一个表的更新会级联到对其他表的更新;由于触发器通常很糟糕,因此存储过程相互调用。对于“简单”的数据库 parm.queries 就可以了,一个简单的 WS 层也可以...
【解决方案3】:

我会说 SP 不可维护且不可扩展。询问任何必须向 SP 繁重的系统添加功能的开发人员。为什么将一半的逻辑放在不同的层中?没有什么可以替代的,只是不要使用它们。

Googled this great post.

【讨论】:

  • 你如何证明第一句话的合理性?我想说任何代码在很大程度上都可以像任何其他代码一样扩展和维护
  • 我的经验。也许我应该说:“对我来说,SP 很难维护,尤其是在规模上,有许多开发人员跨越不同的大陆。”如果整个系统都是SP,那是一回事。我还没有见过这样的系统。
  • 我不确定那篇文章是否很棒。那家伙也反对使用数据库约束(例如外键)。我认为他也反对在数据库级别使用主键或唯一约束。对我来说似乎完全疯了。
  • 托尼·马斯顿的帖子不包含“主要”或“独特”等词,因此,请自行得出结论。
【解决方案4】:

我经常听到这样的论点,即如果您有多个应用程序连接到数据库,SP 就很好,或者它使错误修复更容易。

这就是服务层的用途!

业务逻辑进入服务层,应用逻辑进入应用/网站。

调试和维护数百个 SP(尤其是如果已生成)比维护通过 ORM 工具与 DB 对话的编写良好的代码要困难得多。

【讨论】:

  • 我喜欢 ORM 工具,它们加快了开发速度——但它们不能替代存储过程来进行复杂的更新。您可能会发现 - 通过分析 - 用 sproc 替换繁重的 ORM 更新将大大提高性能。假设你的数据库操作很复杂,当然......
  • 我同意,如果您发现瓶颈并且 SP 解决了它,那么这将是一个有效的用例。
  • +1 提醒我们使用服务层 - 并且是令人愉快的 ;-)
  • 唯一的问题是在某些企业情况下,可能有各种应用程序访问数据库,这些应用程序都运行在不同的平台上,让它们都通过服务层运行可能很困难。您可以采用 SOA 方法,但我认为人们会发现 SP 更容易。
  • 这是一个完全独立的问题,但既然可以编写一个应用程序,为什么还要编写两个应用程序呢?将业务逻辑拆分到一个单独的应用程序中,您的工作量增加了一倍,性能降低了一半。
【解决方案5】:

如果您只关心速度,SP 可能是您的最佳选择。但是,如果您关心可伸缩性或可维护性,SP 可能不是最好的。我们的架构是建立在 SP 之上的,经过 10 年的代码,它很难维护,而且漏洞百出。一个好的 ORM 映射器可能是一个更好的选择。

【讨论】:

  • SP 不适合你并不意味着它不能工作。 SP可以做对,ORM可以做错
【解决方案6】:

可维护性 可能SP更好。如果维护数百个 SP 很困难,那么在业务层组件中维护它们就更难了。

性能 查询缓存可能会产生接近 SP 的性能。但它们无法在各种平台的各种数据库中匹配 SP 的性能。网络延迟是另一个值得关注的领域,尽管如今差距正在缩小。

调试 使用 SP 可能比调试业务层 + 数据库层放在一起要容易。

使用 SP 可以获得更多 +ve 点数。

但看看现代编程趋势,出于大量业务原因,采用“N”层架构比坚持“旧”基于 SP 的方法更“明智”。

好的系统应该两者兼得。大概遵循80-20原则,20为SP。

【讨论】:

    【解决方案7】:

    存储过程对于 CRUD 的东西很有用——例如最好在数据库中执行的专门的跨表逻辑。 CRUD 操作不应使用 SP,除非它们是像 TableAdapters 这样的 ORM 工具自动生成的输出。

    【讨论】:

      【解决方案8】:

      ORM 和 LINQ to SQL 似乎是取代 StoredProcs 的当前趋势。

      我个人使用过 ORM,发现它更容易维护和支持。

      说明使用存储过程的一些原因,从没有正当理由开始。

      当您为多个应用程序提供服务时,您确实对存储过程提出了很好的看法;它们本质上变成了 DAL,通常在其中包含一些业务逻辑。

      【讨论】:

      • 看,像这样的事情真的让我感到困惑..查看摘要。 theserverside.net/news/thread.tss?thread_id=31953
      • 但在所有语言都支持 ORM 和 LINQ 之前,我们仍将使用 SP(尽管我希望 LINQ 能够更快地传播!)
      • 这篇服务器端文章与许多其他文章一样(再次)错过了重点。反对存储过程的人(对于大多数但不是所有情况)并不主张将 sql 从存储过程移动到 DAL。他们提倡一起删除sql!这怎么可能不更易于维护。
      • 克雷格,你能解释一下你所说的“他们提倡一起删除 sql。我也可能错过了重点。
      • 如果你使用像 nHibernate 这样的 ORM,SQL 是由框架在后台自动生成的。如果他们不想,开发人员不需要编写任何 SQL。在我的网站 www.jobtree.com.au 中,我编写的唯一 SQL 用于一些夜间批处理。
      【解决方案9】:

      当您将 SP 与逻辑与数据库本身结合起来时,您可以有效地将数据库转换为类似于应用程序服务器的东西。

      当这是最方便的锤子时,它很有意义。但现在随着应用服务器的普遍可用性,将它们用于集中逻辑和业务规则等事情并仅依赖数据库进行持久性更有意义。

      【讨论】:

        【解决方案10】:

        双方都提出了一些好观点(事实上),但没有人对安全影响做出太多重视。在 SP 中封装所有 DB 交互意味着您可以锁定 DB,以便严格控制与数据的任何交互。

        如果您想到封装,您可以将 DB 视为一个对象,将 SP 视为将对象功能暴露给外界的方法和属性。

        在一些较大的开发环境中,不允许 UI 和业务层开发人员靠近 DB。他们指定他们的要求,而单独的团队通过 SP 提供和接口。

        有一些不使用 SP 的充分理由和一些只使用它们的充分理由 - 取决于您的应用程序和您的环境。但请放心,SP 不会很快消失。

        【讨论】:

          【解决方案11】:

          从这个网站表现不佳的情况来看,我认为主要的瓶颈是数据库。

          我不相信他们使用的 LINQ 2 SQL ORM 比 sproc 快一点。

          【讨论】:

            【解决方案12】:

            这还取决于您的存储过程在做什么。

            例如,如果它只是

            select a from b where x = y
            

            那么存储过程可能是矫枉过正。但我个人倾向于使用存储过程在数据库中返回多个结果集和页面结果。

            在我的情况下,我可以看到使用它们的好处。这是一个额外的处理层,但如果您的代码组织良好且符合逻辑,我个人认为不会有太多麻烦。

            具有存储过程的好项目总是比没有存储过程的劣质项目好,反之亦然。

            【讨论】:

              【解决方案13】:

              只是在这里提出我的小建议。在 SQL 2005 之前(可能比这更远),SP 更快。但是,SQL Server 2005 及更高版本经过了真正的优化,可以随时缓存您的查询。事实上,我们已经将一个 Web 应用程序转移到了一个新的 SQL 服务器上。该应用程序开始时每个人都运行缓慢。一切都需要“3/4 秒”或 1 秒才能运行。然后 SQL 开始编译最常用的查询,一切从慢到快。

              当然,当有很多人在上面运行时,我们交换了服务器(这可以解释为什么一开始它很慢)。但是相信我。 SP还没有结束。除了绑定到应用程序之外,它们还有其他用途。

              【讨论】:

              • 由于 SQL Server 7 查询已被缓存。
              【解决方案14】:

              这个问题也涉及到one posted earlier today

              【讨论】:

                【解决方案15】:

                SP 通常在开发过程中使用得太早。当你有一个瓶颈 sql 语句时,应该使用它们。例如,您可能不需要 SP 来为应用删除或创建用户。对于大多数公司来说,这应该是相当静态的。

                【讨论】:

                • 没错。 SP 并不是一个不应该被创建的邪恶事物(很多非 ORM 用户似乎都认为我们是这样认为的)。超级复杂的查询是应用程序中的一个常见瓶颈,非常适合存储过程。
                • 如果“查询”是指“一组 T-SQL 语句”,那么我必须同意。但是,如果您的字面意思是“查询”,即单个 SELECT,那么我一定不同意。举一个简单/愚蠢的例子,删除应用程序的用户可能会级联删除用户曾经在多个表中创建的每条记录...
                • 为什么不能用来删除用户?需要运行很多查询来删除用户(打破 FK,在适当的情况下删除依赖对象)。我编写了一次 SQL,然后将其粘贴到 SP 中。现在这是一个罐头常规。我的“业务层”可以调用它,或者复制/粘贴。
                【解决方案16】:

                难道 Jeff Atwood知道存储过程将永远存在,只是试图激发思考和辩论?我喜欢认为他真正想做的是写一篇有说服力的文章,题为“存储过程被认为是有害的”:)

                【讨论】:

                  【解决方案17】:

                  我可能会补充一点,最好在数据库级别完成一些工作。
                  例如SQL 2005 中的交叉表结果,递归查询。

                  我同意一些简单的东西,如 SELECT、INSERT、UPDATE、DELETE 可以由 ORM、Linq 处理。

                  因此,说存储过程的时代已经结束是愚蠢的。
                  有多少人真正需要担心数据库平台的变化(SQL 到 Mysql、Oracle)?

                  【讨论】:

                    【解决方案18】:

                    这部分是由非关系数据存储的可用性驱动的。 SPs 通常意味着关系数据库; ORM 和 Linq 提供了创建比 SQL 提供的更丰富的抽象层的能力,并且有时可以更好地匹配我们在设计的其他部分中使用的抽象(“阻抗不匹配”问题。)

                    它也可以被认为是建筑的功能。恕我直言,SP 与经典的表驱动应用程序非常匹配,并且可以提供一种在业务对象级别构建抽象层的便捷方法。

                    如果您的数据存储是 xml 或分析数据库,它们就不那么方便了。

                    【讨论】:

                      【解决方案19】:

                      如果您正在运行共享同一个数据库的多个企业应用程序,存储过程/视图/函数仍然是数据库的一个很好的“接口”。

                      App#1 - 您需要添加新的关系/字段,或将可为空的列更改为非空。

                      App#2-10 - 可以使用也可以不使用这个数据库对象

                      我要做的第一件事是检查我的数据库对象依赖关系以确定它的使用方式以及是否会破坏任何东西。好吧,猜猜看,如果您有一堆通过 ORM / SQL 进行的外部查询,您将不知道依赖关系。

                      这是我发现直接访问表的唯一缺点。

                      对于使用单个数据库的单个应用程序,这确实不是问题。尽管除了数据库之外,您仍然需要查看应用程序代码的依赖项。

                      【讨论】:

                        【解决方案20】:

                        呸!

                        ORM、SP、View、Magic Wands 等等。

                        每个“工具”在你的腰带上都有它的位置,明智地使用你拥有的工具。

                        唯一“改变”(真正改进)的是一些 ORM 已经内置了很好的缓存工具,并且 MySql 和 Sql 2005+ 可以处理动态或临时查询/执行计划缓存。

                        在您的数据库服务器上抛出各种动态 sql 的潜在性能损失已经有所缓解。现在没有存储过程更容易。存储过程不会去任何地方。

                        【讨论】:

                          猜你喜欢
                          • 2013-08-14
                          • 2016-04-17
                          • 2011-02-23
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2017-03-24
                          • 1970-01-01
                          相关资源
                          最近更新 更多