【问题标题】:ExecuteReaderAsync causes sql query to take longer to finish?ExecuteReaderAsync 导致 sql 查询需要更长的时间才能完成?
【发布时间】:2014-06-14 13:20:18
【问题描述】:

我有这个由多个客户端进程共享的 SQL 服务器实例。我希望用尽可能短的时间完成查询。

假设一个调用需要从这个共享的 Sql Server 读取 1k 到 10k 条记录。我的自然选择是使用 ExecuteReaderAsync 来利用异步优势,例如重用线程。

我开始怀疑异步是否会带来一些开销,因为每次调用 ExecuteReaderAsync 时执行可能会停止和恢复。确实如此,与使用 ExecuteReader 的实现相比,完成查询的总时间似乎会更长。这有意义吗?

【问题讨论】:

标签: sql-server async-await


【解决方案1】:

无论是使用同步还是异步调用 SQL Server,对于 SQL Server 所做的工作和 ADO.NET 为序列化和反序列化请求和响应所做的 CPU 密集型工作都没有区别。所以无论你选择什么,差异都会很小。

使用异步并不是为了节省 CPU 时间。它是关于节省内存(更少的线程堆栈)以及在 UI 应用程序中拥有良好的编程模型。

据我所知,事实上异步从未节省 CPU 时间。它增加了开销。如果您想节省 CPU 时间,请使用同步方法。

在低并发工作负载中使用异步的服务器上没有任何价值。它增加了开发时间和 CPU 成本。

【讨论】:

  • 我不关心客户端 CPU 时间。我担心 Sql Server 在操作过程中花费的时间。经过一番研究,我相信我想使用 ExecuteReadAsync,将任务存储在队列中,然后在关闭数据库连接后处理这些任务。否则,处理返回任务所花费的时间将延迟每个 ExecuteReadAsync 调用。这样,客户端将一个接一个地调用 ExecuteReadAsync,没有任何延迟。这有意义吗?
  • 您想执行多个调用对我来说是新的。当然,这允许并行化。您不能只运行一次返回所有数据的查询吗?这可以节省大量的开销。 (当我有这些信息时,我会完全回答你的评论。)
  • 每个查询可能返回 1k 到 10k 条记录。这是每个的 ExecuteReadAsync。每条记录都有一个需要解析的二进制字段。
  • 我会为此使用任何标准的并行化策略。像 PLINQ 或 Parallel.ForEach 或多个异步方法,每个方法执行一个查询并处理结果。为此,您使用异步 IO 还是同步 IO 并不重要。您不能通过更改调用方法的方式来使网络或服务器更快。并行度越高,使用异步 IO 的内存优势就越多。不过,这对花费的总时间没有帮助。为什么会这样?
  • 嗯,客户端与服务器交互的时间是:(#records * (timeof(ExecuteRead) + timeof(HandlingReadData))) vs (#records * timeof(ExecuteReadAsync))
【解决方案2】:

异步方法和同步方法之间的区别在于异步调用将导致编译器生成状态机,而同步调用将在与数据库的工作完成时简单地阻塞。

IRL,最好的选择方法是对这两种方法进行基准测试。正如 usr 所说,与执行查询所需的时间相比,这些差异通常是可以忽略的。异步在可以节省资源的地方会更亮,例如分配新线程

关于异步性能的帖子很多:

  1. Async await performance
  2. The zen of async: best practices for best performance
  3. Async Performance: Understanding the Costs of Async and Await

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-27
    • 2015-10-29
    • 1970-01-01
    • 1970-01-01
    • 2014-01-15
    • 1970-01-01
    相关资源
    最近更新 更多