并行化考虑因素

时间:2010-11-19 17:21:33

标签: c# sql-server multithreading task-parallel-library

我希望得到社区对此的看法。如果我有一个严重受DB / IO限制的进程,使用任务并行库并行化各个进程路径有多聪明?

我将使用一个例子......如果我有一堆项目,我需要做以下操作

  1. 查询数据库以查找项目列表
  2. 执行一些聚合操作,根据动态参数列表对某些项目进行分组。
  3. 对于每个分组结果,根据汇总结果查询数据库。
  4. 对于每个分组结果,进行一些数值计算(3和4将按顺序进行)。
  5. 对#3
  6. 中计算的结果进行一些插入和更新
  7. 为#1
  8. 中返回的每个项目执行一些插入和更新

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

    但我想在本地计算机上逻辑分发任务,以便它能够像数据库一样快地处理我们,而不必等待我们的任何事情。我已经完成了一些模拟原型,我用Thread.Sleeps替换了db调用(我还尝试了一些与.SpinWait相比的变化,速度快了一百万倍),而并行版本比当前实现更快,完全是串行的而且根本不平行。

    我害怕的是在SQL服务器上施加了太大的压力......在我走得太远之前,我应该考虑哪些因素?

2 个答案:

答案 0 :(得分:2)

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

我对你的任务描述并不是很了解,但几乎听起来这些任务应该直接在数据库中执行(我认为有些细节不可能实现?)

答案 1 :(得分: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,但概念转换得非常好。