【问题标题】:Is this a valid benefit of using embedded SQL over stored procedures?这是在存储过程上使用嵌入式 SQL 的有效好处吗?
【发布时间】:2009-06-16 15:22:55
【问题描述】:

这里有一个我没听过的关于 SP 的论点。火焰喷射器,对向下滴答声要温柔,

由于每次访问数据库服务器都会产生开销,因此我建议将 SQL 置于 SP 中而不是嵌入式代码的一个可能原因是,您可以更轻松地进行更改而不会影响性能。

例如。假设您需要执行返回标量整数的查询 A。

然后,稍后,需求发生变化,您决定标量的结果是 > x,然后,只有这样,您才需要执行另一个查询。如果您在 SP 中执行了第一个查询,您可以轻松地检查第一个查询的结果并有条件地在同一个 SP 中执行第二个 SQL。

如果不执行单独的查询或不必要的查询,您将如何在嵌入式 SQL 中有效地做到这一点?

这是一个例子:

--This SP may return 1 or two queries. 

SELECT @CustCount = COUNT(*) FROM CUSTOMER 

IF @CustCount > 10 
   SELECT * FROM PRODUCT 

这/在嵌入式 SQL 中执行此操作的最佳方法是什么?

【问题讨论】:

    标签: sql performance stored-procedures


    【解决方案1】:

    A very persuasive article

    SQL 和存储过程将在您的数据期间存在。

    客户端语言来来去去,您每次都必须重新实现嵌入式 SQL。

    【讨论】:

    • 我希望我能为这篇文章多次投票给你。我以前从未听说过的令人信服的观点。
    • 无论是否嵌入另一种语言,SQL 都不会改变。无论如何,您应该尽可能地减少您编写的自定义 SQL。 lostechies.com/blogs/chad_myers/archive/2008/02/21/…
    • @chadmyers:当您在更大的系统上工作时,ORM 会惨遭失败。他们无法处理设计合理的数据库,因为它们决定了您的设计。它不会使我的答案无效,因为您仍然必须每次都重新实现 ORM。存储过程是一种方法
    • 我听说过“当你在更大的系统上工作时”的谬论 - 我一直在更大的系统上工作,除非你在谈论 Facebook big,在这种情况下 RDBMS 会失败。只要 RDBMS 工作,ORM 就工作。如果 ORM 失败,那么通常你不应该首先使用 RDBMS。 ORM 用于 CRUD 端,但对查询/报告端没有那么有用。在这种情况下,SP 并没有多大用处,无论如何您都需要不同的策略(OLAP、非规范化存储等)。 SP 的论点通常都是基于谬误和无知,恕我直言
    • @chadmyers:那么我们将不得不不同意
    【解决方案2】:

    在您提供的示例中,节省的时间是通过网络发送单个标量值和单个后续查询。这在任何合理的情况下都是微不足道的。这并不是说使用 SP 可能没有其他有效的性能原因。只是这不是这样的原因。

    【讨论】:

    • 总是微不足道的吗?我认为,如果您正在从 Web 服务器执行两个单独的 SQL 到优化它们之间的管道的数据库,这可能是微不足道的,但是这些事件会随着时间的推移而成倍增加,从而使您的应用程序运行缓慢,但是如果你在和一个胖客户打交道?
    • 我认为它总是微不足道的。如果标量和查询字符串的行程时间是查询执行周期的重要部分,则您的查询太小(例如,您正在执行一千个等于查询而不是 IN 查询,或者为每一行重新查询在结果集中等)如果您遇到这样的情况,这代表了显着的节省,那么您的系统还有其他更大的问题。
    • 我的观点是,简单地让服务器跳来执行查询是昂贵的,无论执行什么 SQL。如果您有一个胖客户端,您希望客户端如何与数据库对话?直接还是通过某种类型的网络服务?如果是后者,我们不是在谈论两跳吗? 1)从胖客户端到Web服务器和2)从Web服务器到数据库?我发现每个跃点(不计算查询时间)大部分时间都在亚秒以下,但我在我们公司的一般经验是网络非常慢,而且 nwetwk 基础设施可能随时更改。
    【解决方案3】:

    我通常不会将业务逻辑放在 SP 中,我希望它们在数据库之外使用我选择的母语。我唯一同意 SP 更好的情况是当有大量不需要从数据库中出来的数据移动时。

    因此,为了回答您的问题,我宁愿在我的代码中包含两个查询,也不愿将其嵌入到 SP 中,在我看来,我正在用一个小的性能损失换取更清晰的东西。

    【讨论】:

      【解决方案4】:

      您将如何有效地做到这一点 嵌入式 SQL 不执行单独的 查询还是不必要的查询?

      取决于您使用的数据库。在 SQL Server 中,这是一个简单的 CASE 语句。

      【讨论】:

      • 嵌入式 SQL 示例怎么样?请参阅我添加到问题中的 SQL sn-p。
      • 您的 sn-p 没有意义,因为一个查询返回一个标量,另一个返回一个表。第二个查询不应该也返回一个标量吗?
      • 我不明白为什么这种区别是相关的。你能解释一下吗?
      • 附加 pt:尽管给出的示例在现实生活中似乎不太可能,但其目的只是提供可用于对话并可由嵌入式 SQL 支持者修改的 SQL,以展示其相同之处结果可以在嵌入式 SQL 中实现。如果你想要一个更现实的例子,我会试着想出一个。
      • 我正在尝试使您的示例与单一职责原则 (en.wikipedia.org/wiki/Single_responsibility_principle) 相协调 - 您是否有一个示例结果数据类型不会改变?一个查询给出计数,另一个给出记录集,有两种不同的用途 - 不知道为什么要将它封装在一个操作中。
      【解决方案5】:

      也许在该存储过程中包含 WHERE 子句:

      WHERE (all your regular conditions)
      AND   myScalar > myThreshold
      

      【讨论】:

      • 嗯。我不想更改第一个 SQL 的结果。我想有条件地执行第二个。请查看已编辑的原始问题,其中包含一个小型 SQL 示例。
      【解决方案6】:

      最近我更喜欢不使用 SP(除非出现 uber 复杂性,其中 proc 会更好......或者 CLR 会更好)。我一直在将存储库模式与 LINQ to SQL 一起使用,其中我的查询以强类型的 LINQ 表达式写入我的数据层。这里的关键是查询是强类型的,这意味着当我重构时,我正在重构直接从数据库表生成的类的属性(这使得从数据库中进行的更改一直非常简单和准确)。虽然我的 SQL 为我生成并发送到服务器,但我仍然可以选择坚持 DRY 原则,因为存储库模式允许我将事物分解成最小的组件。我确实有可能会访问服务器的问题,并且根据查询结果,我可能会发现我需要再次访问服务器。我不担心这个。如果我以后发现它成为一个问题,那么我可能会将该代码重构为更高效的代码。这里最重要的是没有一颗灵丹妙药。我倾向于开发新的应用程序,这使得这种开发方法对我来说是最有效的。

      【讨论】:

      • LINQ 让我很感兴趣,尽管除了 hello world 示例之外,我还没有使用过它。对我来说,它的强绑定部分非常吸引人。 LINQ 的吸引力,对我来说,可能足以让我远离 SP,但我对“如果以后出现问题,可以对其进行重构”的想法持谨慎态度。
      • 如果您有良好的关注点分离(例如存储库模式),您的应用程序不了解存储过程、内联 sql、LINQ to SQL、NHibernate、实体框架、XML 等。唯一的问题我在使用 LINQ to SQL 或 Entity Framework 时遇到的是它们不使用 truley POCO 类型类(尽管 EF 更接近)。这对我来说是一个可以接受的权衡,因为它减少了我需要做的工作量。如果您需要,NHibernate 可以很好地提供这个功能!这使得重构技术变得非常简单。并且到处使用 StructureMap!
      【解决方案7】:

      SP 的好处:

      1. 性能(预编译)
      2. 易于更改(无需编译应用程序)
      3. 基于 SQL 集的功能可以轻松完成非常困难的数据任务

      缺点:

      1. 严重依赖所使用的数据库引擎
      2. 使升级部署更加困难(您必须部署应用程序 + 脚本)

      我的 2 美分...

      关于你的例子,可以这样做:

      select * from products where (select count(*) from customers>10)
      

      【讨论】:

      • "Performance (are precompiled)" SQL Server 7 是这样,Sql Server 2000 不那么如此,Sql Server 2005 不存在。2008 年,我会请求不同,相反是真的。
      • @mxmissile,有趣的一点,我会检查一下,这就是我喜欢 SO 的原因,你每天都能学到很多东西......
      • SQL Server 2005/2008 对存储过程和常规查询进行执行计划缓存,将它们视为基本相同。 “与批量动态 SQL 相比,存储过程和触发器在 SQL Server 中的主要性能优势是它们的 SQL 语句始终相同。”来源 [msdn.microsoft.com/en-us/library/ms190201.aspx] 和 [msdn.microsoft.com/en-us/library/ms181055.aspx] 但是,我不确定你怎么能说相反的说法是正确的。
      • 是的,SQL Server 2005/2008 对常规查询进行执行计划缓存——但只有在“新”查询与计划所基于的查询匹配时,它才会重用现有计划。高学历。我已经看到额外的空白会导致新的编译......
      • 啊!很好!我看到了pt。我只是不喜欢无条件执行第二个 SQL,但我意识到优化器可能不会重新执行之前执行的 () 内部 SQL。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-09
      • 2011-02-20
      • 2019-03-12
      • 1970-01-01
      • 1970-01-01
      • 2010-12-12
      • 1970-01-01
      相关资源
      最近更新 更多