ADO.NET SQL Server性能:多结果集 vs. 多命令执行

3

使用连接池或者假设在多次调用之间连接不会关闭,对于执行具有多个结果集的存储过程和多次执行存储过程之间是否存在网络或服务器性能差异,以及差异的显著程度是多少。

伪代码如下:

using(new connection)
{
  using (datareader dr = connection.Execute(Command))
  {
    while (dr.NextResult())
    {
      while (dr.Read())
      {
        SomeContainer.Add(Something.Parse(dr));
      }
    }
  }
}

vs

using(new connection)
{
  using (datareader dr = connection.Execute(Command))
  {
    while (dr.Read())
    {
      SomeContainer.Add(Something.Parse(dr));
    }
  }

  using (datareader dr = connection.Execute(Command))
  {
    while (dr.Read())
    {
      SomeContainer.Add(Something.Parse(dr));
    }
  }
}

我猜第一个应该会更快(对象创建次数较少)。尝试创建一个测试来测量时间。 - garik
4个回答

4
第一种是单个往返到服务器,第二种是不同的往返。由于网络延迟、解析请求的时间、设置执行上下文的时间等,往返会产生惩罚。但是,对于除最关键的应用程序以外的所有应用程序来说,这种惩罚几乎可以忽略不计。 因此,请按照更容易理解、编写、调试和维护的方式进行操作(在我看来,这将是第二个选项)。您可能无法衡量差异。

那么即使连接保持打开状态,它也会创建一个新的往返?你说这只是噪音,但如果我们谈论的是 Web 上下文,每 3 或 4 分钟可能会有一千个对该块的调用,并且结果集为 10 或 15 个而不是 2 个,那么噪音是否会变得显著或者完全可以忽略不计? - Jimmy Hoffa
每个“Execute”都是一次往返:请求必须发送到服务器,服务器必须创建一个任务来处理它,任务必须选择一个工作线程运行,一旦启动,它必须被解析,然后启动执行。我仍然认为所有这些都加起来只是最小的噪音。在大约3分钟内的每1k个请求中,您将得到70-100个与10-15个请求每秒相比。设置一个测试并查看是否可以测量出差异。 - Remus Rusanu
如果您的客户在香港,而服务器在欧洲,往返时间显然更为重要。那么其他SQL Server客户端、监控等方面呢? - gbn
如果网络延迟明显,往返惩罚至少与延迟一样大。但是对于运行在海外的客户端,我会考虑重新设计使用本地数据服务器,并使用可靠的传递机制将数据推送到各个洲际。这不是出于性能原因,而是出于可用性原因首先考虑。 - Remus Rusanu
我测试了这两种选项,因为我有同样的问题。结果是,在我的测试环境中(使用连接池),多个调用与一个单一调用并获得多个结果集相比,性能慢大约三倍。因此,从性能上考虑,请使用多个结果集。 - Martin

1

我不同意,我几乎总是选择第一种方法(这确实取决于特定的情况),但总的来说,最好有一个存储过程返回2个结果集,而不是调用2个返回单个数据集的不同存储过程,正如@Remus解释的那样(网络延迟等原因)。在大多数情况下,差异并不可忽略。


0
建议您自己分析并比较两种方法的效率,因为哪种更高效可能取决于数据量和用户数量等因素。我倾向于认为在网络上只进行一次往返更好,但最好尝试两种方法并进行测量,这样您就会知道哪种更好。

-1

在你的两种情况下都使用了连接池,因此它对于你确定效率并不重要。

如果你可以在单个调用中接收所有结果,那么比多次调用自然更有效。考虑一个简单的例子,选择10个单独的东西与使用“in”子句一次选择所有10个。这是向服务器发送1个查询和1个响应解析,而不是每个10个的回程。这就是Remus所说的往返。

在轻负载场景下,这很可能是名义上的,但随着(如果)你扩展规模,聊天可能会开始成为问题。您的连接池有一个可以在某些时候达到的限制。

如果你在调用之间返回相同类型的数据,我会选择选项1。

但是,还需要考虑维护和重用。如果你返回不同的数据(即:获取特定视图所需的所有数据),我会选择选项2,并根据需要优化到较少的调用。


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