【问题标题】:Using Parallel.ForEach and Tasks.Factory.StartNew for database insertion/updation使用 Parallel.ForEach 和 Tasks.Factory.StartNew 进行数据库插入/更新
【发布时间】:2014-06-09 12:01:07
【问题描述】:

我在 .Net 4.0 中工作,我的代码应该这样做:

我有一个向用户公开的 WebAPI。在这我有一个 Objects 的集合。基本上是一个包含一些对象的 ConcurrentBag 。我必须遍历此集合中的每个对象,然后在 Database 中插入/更新其数据。对象的数量可能很高(200-300)。除此之外,如果可以有多个并发用户使用我的 API。

现在,插入/更新非常慢,因为每条记录都会连接到数据库,这使得这个过程非常慢。不幸的是我不能改变这个逻辑。

为了提高性能,我使用了 Parallel.ForEach 而不是常规的 foreach,因为每次迭代都是不同的。另外,我正在为数据库中的每个插入创建一个单独的任务

这是我的代码

 var tasks = new List<Task>(allRecordings.Count);//Creating a Task List 
 Parallel.ForEach(allRecordings, recording =>
        {
            var recordingItem = recording;
            //Lines oF Code 
            //                                        

         if ( some Conditions){
          var task = Task.Factory.StartNew(
                               () => SaveRecordingDetailsToDb(ref recordingItem, device.Locale));
           recording.Title = recordingItem.Title;
           recording.ProgramId =recordingItem.ProgramId;
           recording.SeriesId = recordingItem.SeriesId;
           tasks.Add(task);//Adding Task to List
           }
         });
         Task.WaitAll(tasks.ToArray()); //Waiting for all Tasks to complete before going back to main   
                                          Function
}

当有多个并发请求使用同一个 API 时,上述块中是否会发生 MemoryLeak 另外,在这里使用 Parallel.ForEach 会比普通的 ForEach 更好吗?

【问题讨论】:

  • " 对于每条记录,都会对数据库进行连接,这使得该过程非常缓慢" - 如果您使用常规 ADO.NET 连接到主要数据库,这听起来不太可能;通常开箱即用地支持自动连接池。目前这需要多少时间?我不确定Parallel.ForEach 是否在这里为您提供帮助(它甚至可能毫无帮助,即使情况变得更糟)
  • 所以这里发生的是当 SaveRecordingDetailsToDb 被调用时,它首先从 MongoDB 检索一些信息,然后在 MS SQL Server 中执行存储的过程。这是遗留代码:(
  • 好吧,它的 SQL Server 部分应该支持连接池。我无法对 mongo 发表评论。回到问题:你有理由认为它可能导致某种泄漏吗?
  • 通过使用数据库的批量插入机制,您可以获得更好的性能。从 MongoDB 中提取所有数据然后使用 SqlBulkCopy 将它们发送到服务器,或者将它们提取到磁盘然后使用 SSIS 处理和导入它们
  • Marc,我唯一担心的是我可能会产生很多线程,每个线程都会连接到 Mongo,然后是 SQL。如果为一个用户创建了 80-100 个线程,并且当有有很多并发用户,这会爆炸吗?

标签: c# .net multithreading task-parallel-library parallel.foreach


【解决方案1】:

TPL(任务并行库)专为计算密集型操作而设计,用于可以并行完成的操作(例如在不同 CPU 内核上的计算)。在您的情况下,您写入数据库,因此,基本上您将某些内容写入文件系统,即这是 IO 操作。 IO 操作不能在纯并行意义上并行执行。如果同时运行多个 IO 操作,它们只会相互中断,因此与一个一个运行它们相比,它们需要更多的时间来完成。当然,数据库服务器应该以某种方式处理这种情况,但它不会比一个一个地向它发送请求快得多,更有可能会更慢。

【讨论】:

  • 我做了一些基准测试,我发现使用 TPL 实际上将时间减少了之前总时间的 1/3。虽然这里的 cmets 提出了建议,但情况会更糟。让我完全困惑是否要坚持这一点
  • 可能是数据库服务器进行了一些优化,例如合并对数据库的请求。
猜你喜欢
  • 2016-10-05
  • 2012-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多