【问题标题】:What factors contribute to ExecuteReader's duration?哪些因素会影响 ExecuteReader 的持续时间?
【发布时间】:2017-03-20 14:17:01
【问题描述】:

我们有一个应用程序,它给人的印象是数据库响应不佳。数据库和应用服务器都没有负载过重,但应用程序花费大量时间通过 ExecuteReader 进行查询。

我们正在测量两件事:SQL Server Profiler 中的批处理和语句持续时间,以及调用 ExecuteReader 和处理它之间的时间。数据的消耗是“微不足道的”,即。只需将数据读入字典列表即可。

Profiler 记录的持续时间通常远小于应用程序记录的持续时间。这些查询只返回几行(通常是一行),因此使用结果集所花费的时间应该很小。 但是我们已经看到应用程序将 150 毫秒查询(由分析器记录)记录为超过 1700 毫秒的实例。

环境:

  • 这不是我们的基础设施。
  • 它是实时的,因此我们无法附加分析器/调试器。
  • 应用服务器至少是虚拟化的。数据库是一个集群。
  • SQL Server 2008R2 和 Windows Server 2008R2。

一个明显的罪魁祸首是网络延迟,但ping 表明从应用程序到数据库服务器的延迟始终小于 1 毫秒。

连接被重复用于多个查询,因此 Open() 时间开销应该已经单独考虑。我预计这可以排除 ExecuteReader 期间的身份验证延迟,但也许我错了?

我们还应该调查哪些其他事情? ExecuteReader 可能会等待哪些其他事情?

【问题讨论】:

  • “连接被重复用于多个查询”——这让我担心——如何为什么连接被重复使用?
  • 在同一个 NHibernate 会话中的多个查询,特别是。
  • 线程之间永远不会共享连接,并且我们关闭了 MARS(查询只会连续运行)。应用程序的某些部分依赖于临时表,这些临时表会在连接关闭时丢失,因此有时需要在多个查询之间保留连接。不过,任何连接都很少能存活超过几秒钟。
  • @Damien_The_Unbeliever 它应该只是一个打开的SqlConnection,然后使用该连接执行多个SqlCommands,而不在每个查询之间关闭它。这很好,因为它与通过 SSMS 中的GO 进行多批次相同。

标签: c# sql-server ado.net sqldatareader


【解决方案1】:

我们已经看到应用程序将 150 毫秒查询(由分析器记录)记录为超过 1700 毫秒。

应用程序究竟是如何记录时长的?使用StopWatch,或者类似的东西?还是来自SqlConnection.RetrieveStatistics()报告的客户统计数据?

您是否检查过运行查询的请求的等待类型字段?在sys.dm_exec_requests DMV 中,有四个字段包含可能在此处有用的信息:wait_typewait_timelast_wait_typewait_resource。即使查询在内部快速将结果返回给 SQL Server,它仍然可能需要专门的线程将这些结果发送回调用者。

另外,尝试一些方法来帮助缩小可能性:

  • 关闭连接池。在ConnectionString 中,使用Pooling=false;。这仍然允许在同一连接上进行多个查询(因此不会干扰临时表的使用)。是的,它会稍微增加总时间,因为它需要对每个连接进行身份验证,但它会排除某些东西“卡住”。

  • 如果可能(但尚未这样做),请在对 ExecuteReader() 的调用中指定 CommandBehavior.SequentialAccess。这可以防止在调用 SqlDataReader.Read() 时对整行进行本地缓存,这有助于当您甚至没有检索到大字符串和/或二进制值,或者如果有很多列而您只抓取一些列。

【讨论】:

  • 谢谢,我没有想到关闭连接池,当然也有助于突出有关设置连接的任何问题!我们没有看到太多等待的方式,但是当发回大量行时,“异步网络 I/O”有时会作为主要的出现。
  • 我很确定Async Network IO 表示应用程序检索结果的速度不够快。因此,无论出于何种原因,延迟都可能存在于应用程序本身中。你对每行的值做了什么?
  • 在大多数情况下,我们将其缓冲为字典列表或类似结构。 Profiling 从未指出这是一个瓶颈。即使对于较大的结果集,我们也倾向于尽快将数据转换为对象,然后关闭阅读器。
  • 不幸的是,我们还没有被告知确切的问题是什么,但它现在已经解决了......我们编写了一个工具github.com/BluewireTechnologies/db-latency 来更详细地为请求的各个阶段计时,它展示了延迟峰值特别影响了 ExecuteReader 调用,即使对于“无操作”查询,例如获取 SQL Server 版本,这有助于排除应用程序端的延迟。几乎没有想到打开连接,尽管在其他运行良好的站点上它占了大部分(大大减少)时间。
  • 哦,很高兴知道,再次感谢!回覆。 CPU 和线程,遗憾的是,我认为我们对集群没有那种级别的访问权限。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-10-09
  • 2016-05-04
  • 2011-10-27
  • 2022-01-14
  • 1970-01-01
  • 1970-01-01
  • 2020-11-28
相关资源
最近更新 更多