【问题标题】:SQL Performance QuestionSQL 性能问题
【发布时间】:2009-02-04 20:01:35
【问题描述】:

我有一个关于 SQL 性能的问题。我会用伪代码来说明我的问题。

我想知道哪个会更好,多少?在每个页面加载时说 10 个项目。在 .NET 中。是不是快很多?快一点?在 SQL 上没有明显的差异?

foreach(item in mylist) {
CallSQLStoredProc(item.id);
}

int[] ids; // array of ids
CallSQLStoredProc(ids)  // stored procedure returns more than one row for each id

【问题讨论】:

    标签: sql optimization performance


    【解决方案1】:

    第二个选项肯定会更快,因为它是单个网络往返,以及单个 SP 调用。

    【讨论】:

      【解决方案2】:

      绝对是第二个,从快 10 倍到快一点不等。

      如果您对 id 所做的任何事情都可以在一组操作中完成,那么您将获得比单独调用 SP 几倍的性能提升。

      我经常有类似这样的触发:

      create procedure proc ( @ids varchar(max) ) as
      select * from users_tbl u
      inner join spiltCSVs(@ids) c
        on c.id = u.id
      --so on and so forth
      

      这是一个基于集合的操作;与在 proc 中使用游标的过程方法相反,或者使用 for 循环迭代调用具有单个 id 的过程。

      【讨论】:

      • 您使用哪个数据库?我正在 SQL Server 中寻找这个函数“spiltCSVs”。谷歌“spiltCSVs”返回我 1 个结果 :-)
      • 这是一个实用函数,每个人都根据需要自己编写。 stackoverflow.com/questions/314824/…
      【解决方案3】:

      因为这不适合 ocdecio 回答的评论...

      只是为了扩展它......在我见过的大多数系统中,网络流量是性能的限制因素(假设经过合理调整的数据库和前端代码并不是绝对可怕的)。即使您的 Web 服务器和数据库服务器在同一台机器上,如果您在两者之间频繁来回调用,进程间通信也可能是一个限制因素。

      【讨论】:

        【解决方案4】:

        在每次页面加载时,还是在页面第一次加载时?我不想对 ASP.NET 页面中的每个回发都这样做。

        要更直接地回答您的问题,如果您能够通过发送多个 ID 获得多条记录,请执行此操作。如果您需要超过 10 个项目,则更高效且更具可扩展性。

        【讨论】:

          【解决方案5】:

          这完全取决于 proc 的编码方式,如果您在第二个 proc 中传入 10 个项目,然后该 proc 使用游标来获取这些行,那么第一次调用可能会更快

          【讨论】:

            【解决方案6】:

            迭代任何东西总是会导致更多的开销。迭代提高性能的情况并不多。

            我的建议一直是在编程中避免两件事:

            1. if then else 语句
            2. 迭代

            您总是会遇到同时使用这两种方法的情况,但使用它们的次数越少,您的应用程序就越有可能运行得更快、更流畅。

            【讨论】:

              【解决方案7】:

              第二个会快多少真的取决于太多的事情。与结果集的大小相比,网络开销可能微不足道。

              还有另一种选择(根据锁定行为,它应该比任何一种都快),即call all of them asynchronously - 然后您的页面可以在最长的页面完成时有效地完成。显然,这将需要一些额外的编码。

              在此示例中,只有一个 SP 开销。我们假设 SP 返回客户端将拆分/处理的单个行集或多个行集:

              int[] ids; // array of ids
              CallSQLStoredProc(ids)  // stored procedure returns more than one row for each id
              

              在此示例中,SP 调用开销是单个调用的 n 倍。并且调用是序列化的:

              foreach(item in mylist) {
                  CallSQLStoredProc(item.id);
              }
              

              在第三种选择中:

              foreach(item in mylist) {
                  StartSQLStoredProc(item.id);
              }
              
              // Continue building the page until you reach a point where you absolutely have to have the data
              
              wait();
              

              这仍然有 n 个 DB 调用开销,但性能改进可能取决于 SQL Server 和网络的容量,以便并行化工作负载。此外,您还可以在页面构建时启动 SQL Server 的工作。

              单个 SP 解决方案仍然可以胜出,特别是如果它可以使用 UNION 组合单个结果集,其中 SQL Server 可以并行化任务。但是,如果结果集具有单独的架构或 UNION 不能很好地执行,多 SP 异步解决方案可以击败它(并且还可以利用在页面中执行其他工作的能力)。

              【讨论】:

              • 如果可以异步完成,那么可以写入数据库引擎并行化。在这种情况下,单次调用仍然会更快。单次调用总是会更快。
              • 不幸的是,SP 中的独立批次没有被 DB 并行化。如果您可以同时将 10 个不同的大流从数据库中流出,那么必须构建 10 个行集然后返回它们的单个调用不能保证更快。我会更新答案来演示。
              【解决方案8】:

              如果您希望应用程序具有可伸缩性,您将希望尽可能多地使用缓存。您应该只运行一次任何共享查询并将结果存储在缓存中。

              至于您的查询,如果您没有在查询中为每个 ID 使用游标,那么它应该会更快,前提是网络延迟会对您的操作产生有意义的影响。如有疑问,请测量。当我实际在我的函数上实现计时以查看不同的事情需要多长时间时,我多次感到非常惊讶。

              在 .net System.Diagnostics.StopWatch 是你的朋友 :)。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2019-04-13
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-02-18
                • 2011-06-12
                • 2015-04-05
                相关资源
                最近更新 更多