【问题标题】:Using Parallel Extensions or Parallel LINQ with LINQ Take将并行扩展或并行 LINQ 与 LINQ Take 结合使用
【发布时间】:2011-02-03 17:28:38
【问题描述】:

我有一个包含大约 500 万行的数据库。我正在尝试为数据库生成 XML 字符串并将它们推送到服务。该服务支持一次获取 1000 条记录,而不是一次执行此操作。目前,这很慢,每 1000 条记录需要 10 秒以上(包括写回数据库和上传到服务)。

我试图让以下代码正常工作,但失败了……我在尝试时遇到了崩溃。有什么想法吗?

    var data = <insert LINQ query here>
    int take = 1000
    int left = data.Count();

    Parallel.For(0, left / 1000, i =>
        {
            data.Skip(i*1000).Take(1000)...
            //Generate XML here.
            //Write to service here...
            //Mark items in database as generated.
        });
        //Get companies which are still marked as not generated.
        //Create XML.
        //Write to Service.

我收到一个崩溃,告诉我索引超出范围。如果left 是 500 万,那么循环中的数字应该不超过 5000。如果我再乘以 1000,我应该不会超过 500 万。我不介意它是否工作了一点,然后失败了,但它只是在 SQL 查询之后失败!

【问题讨论】:

  • “索引越界”异常告诉我问题可能不直接出现在您包含的代码中。您能否提供有关数据查询的更多信息,以及您在跳过/采取后做什么?如果可能的话,简化你自己的代码,直到你有一个导致异常的最小示例,然后发布。还要告诉我们错误实际发生在哪一行。
  • 看看我的回答 - 你的代码有错误
  • 感谢小伙子们的 cmets。当我进行拍摄时发生错误(data.Skip(i * 1000).Take(1000)。似乎@Andrey在我的代码中发现了一个错误......请参阅下面的答案......

标签: c# .net linq parallel-extensions


【解决方案1】:

我认为它不喜欢您的最后一个索引值 - 它应该是左 / 1000 -1,而不是左 / 1000:

Parallel.For(0, left / 1000 - 1, i =>
        {
            data.Skip(i*1000).Take(1000)...
            //Generate XML here
            //Write to Service here...
            //mark items in DB as generated
        });

【讨论】:

  • 噢!谢谢你的提示。我已经更改了代码以使用自定义分区,因为这似乎比我的原始代码更干净。它还考虑了(从外观上看)我在修复之后的其余部分......
【解决方案2】:

我怀疑 index out of bounds 错误是由当前显示的代码以外的代码引起的。

话虽如此,这可以以更清洁的方式处理。您应该考虑切换到using a custom partitioner,而不是使用这种方法。这将大大提高效率,因为每次调用 Skip/Take 都会强制重新评估您的序列。

【讨论】:

  • 好的,所以除了我的代码有点错误(哎呀!)似乎这个自定义分区器是要走的路。我想我仍然需要使用需要,但它确实按照我希望它在早期测试中的工作方式工作。等待重建数据库,所以只用少量数据进行测试,但我认为这一切都很好!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-29
  • 2019-08-01
  • 2016-04-10
相关资源
最近更新 更多