哪些因素会影响 ExecuteReader 的持续时间?
What factors contribute to ExecuteReader's duration?
我们有一个应用程序给人的印象是由于数据库响应不佳而成为瓶颈。数据库和应用服务器的负载都不重,但应用程序花费大量时间通过 ExecuteReader 进行查询。
我们正在测量两件事:SQL Server Profiler 中的批处理和语句持续时间,以及调用 ExecuteReader 和处理它之间的时间。数据的消耗是 'trivial' 即。简单地将数据读入字典列表。
Profiler 记录的持续时间通常比应用程序记录的持续时间短得多。这些查询 return 只有几行(通常是一行),因此使用结果集所花费的时间应该很小。
但是我们已经看到 150 毫秒的查询实例(由分析器记录)被应用程序记录为超过 1700 毫秒。
环境:
- 这不是我们的基础设施。
- 它是实时的,所以我们不能附上 profiler/debugger。
- 至少应用服务器是虚拟化的。数据库是一个集群。
- SQL 服务器 2008R2 和 Windows 服务器 2008R2。
一个明显的罪魁祸首是网络延迟,但 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_type
、wait_time
、last_wait_type
和 wait_resource
。有可能即使查询在内部快速将结果返回到 SQL 服务器,它仍然需要专门一个线程将这些结果发送回调用者。
另外,一些尝试只是为了帮助缩小可能性:
关闭连接池。在ConnectionString中,使用Pooling=false;
。这仍然允许在同一个连接上进行多个查询(因此不会干扰临时表的使用)。是的,它会略微增加总时间,因为它需要对每个连接进行身份验证,但它会排除某些东西变得 "stuck".
如果可能(并且尚未这样做),请在对 ExecuteReader()
的调用中指定 CommandBehavior.SequentialAccess
。这可以防止在调用 SqlDataReader.Read()
时对整行进行本地缓存,这在存在您甚至没有检索的大字符串 and/or 二进制值时有帮助,或者如果有很多列而您只抓取一个很少。
我们有一个应用程序给人的印象是由于数据库响应不佳而成为瓶颈。数据库和应用服务器的负载都不重,但应用程序花费大量时间通过 ExecuteReader 进行查询。
我们正在测量两件事:SQL Server Profiler 中的批处理和语句持续时间,以及调用 ExecuteReader 和处理它之间的时间。数据的消耗是 'trivial' 即。简单地将数据读入字典列表。
Profiler 记录的持续时间通常比应用程序记录的持续时间短得多。这些查询 return 只有几行(通常是一行),因此使用结果集所花费的时间应该很小。 但是我们已经看到 150 毫秒的查询实例(由分析器记录)被应用程序记录为超过 1700 毫秒。
环境:
- 这不是我们的基础设施。
- 它是实时的,所以我们不能附上 profiler/debugger。
- 至少应用服务器是虚拟化的。数据库是一个集群。
- SQL 服务器 2008R2 和 Windows 服务器 2008R2。
一个明显的罪魁祸首是网络延迟,但 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_type
、wait_time
、last_wait_type
和 wait_resource
。有可能即使查询在内部快速将结果返回到 SQL 服务器,它仍然需要专门一个线程将这些结果发送回调用者。
另外,一些尝试只是为了帮助缩小可能性:
关闭连接池。在ConnectionString中,使用
Pooling=false;
。这仍然允许在同一个连接上进行多个查询(因此不会干扰临时表的使用)。是的,它会略微增加总时间,因为它需要对每个连接进行身份验证,但它会排除某些东西变得 "stuck".如果可能(并且尚未这样做),请在对
ExecuteReader()
的调用中指定CommandBehavior.SequentialAccess
。这可以防止在调用SqlDataReader.Read()
时对整行进行本地缓存,这在存在您甚至没有检索的大字符串 and/or 二进制值时有帮助,或者如果有很多列而您只抓取一个很少。