0

我想了解社区对此的看法。如果我有一个严重依赖 DB/IO 的进程,那么使用 Task Parallel 库并行化各个进程路径有多聪明?

我举个例子……如果我有一堆物品,我需要做以下操作

  1. 查询数据库以获取项目列表
  2. 执行一些聚合操作以根据动态参数列表对某些项目进行分组。
  3. 对于每个分组结果,根据聚合结果在数据库中查询某些内容。
  4. 对于每个分组的结果,做一些数值计算(3 和 4 将依次发生)。
  5. 对 #3 中计算的结果进行一些插入和更新
  6. 对 #1 中返回的每个项目进行一些插入和更新

从逻辑上讲,我可以在步骤#3、#5、#6 中并行化为任务图,因为其中一项与前一项的结果无关。但是,这些中的每一个都将在数据库(sql server)上等待,这很好,我知道我们只能处理 SQL server 允许的范围内。

但是我想在本地机器上逻辑地分配任务,以便它处理的速度与数据库允许我们一样快,而不必等待我们结束的任何事情。我做了一些模拟原型,我用 Thread.Sleeps 替换了 db 调用(我还尝试了 .SpinWait 的一些变体,它快了一百万倍),并且并行版本比当前的实现快得多,完全是串行的而且根本不平行。

我担心的是给 SQL 服务器带来太大的压力......在我走得太远之前,我应该考虑什么?

4

2 回答 2

2

如果并行版本比串行版本快得多,我不会担心你的 SQL 服务器的压力......当然,除非你正在执行的任务与其他一些重要或时间关键的操作相比是低优先级的在数据库服务器上执行。

我不太了解您对任务的描述,但听起来更多这些任务应该直接在数据库中执行(我想有一些细节使得这不可能?)

于 2010-11-19T17:30:04.680 回答
1

另一种选择是创建一个管道,以便第二组的步骤 3 与第一组的步骤 4 同时发生。如果您可以在第 5 步重叠更新,也可以这样做。这样,您就可以进行并发 SQL 访问和处理,但不会对数据库造成过多负担,因为您一次只能进行两个并发操作。

因此,您按顺序执行第 1 步和第 2 步(我假设)以获得需要进一步处理的组的集合。然后。你的主线程开始:

for each group
  query the database
  place the results of the query into the calc queue

第二个线程为结果队列提供服务:

while not end of data
  Dequeue result from calc queue
  Do numeric calculations
  place the results of the query into the update queue

第三个线程服务于更新队列:

while not end of data
  Dequeue result from update queue
  Update database

System.Collections.Concurrent.BlockingCollection<T>对于这种事情,这是一个非常有效的队列。

这里的好处是,如果您可以通过添加多个计算线程或查询/更新线程来扩展它,如果 SQL Server 可以处理更多并发事务。

我在日常合并/更新程序中使用了与此非常相似的东西,效果非常好。该特定进程不使用 SQL 服务器,而是使用标准文件 I/O,但概念转换得很好。

于 2010-11-19T18:33:25.013 回答