哪些因素会影响 ExecuteReader 的持续时间?

What factors contribute to ExecuteReader's duration?

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

我们正在测量两件事:SQL Server Profiler 中的批处理和语句持续时间,以及调用 ExecuteReader 和处理它之间的时间。数据的消耗是 'trivial' 即。简单地将数据读入字典列表。

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

环境:

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

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

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

we've seen instances of a 150ms query (as recorded by the profiler) being recorded as over 1700ms by the application.

应用程序究竟是如何记录持续时间的?使用 StopWatch 或类似的东西?或者来自 SqlConnection.RetrieveStatistics()?

报告的客户统计数据

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

另外,一些尝试只是为了帮助缩小可能性:

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

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