1

我正在使用 C# MongoDB 驱动程序从 MongoDB 实例中的大型(超过 200 万条记录)数据生成报告。获取所有记录并在服务器端处理它们很慢,所以我一直在尝试不同的东西。

输入是一个任意长度的列表,然后代码必须做的是查询包含 Guids 输入的记录的大型(200 万条记录)集合。

输入数据集 {A, B, C} {1-A, 2-A, 3-A, 4-C, 5-B, 6-C, 7-Z, 8-B .... 1000-Z}

A - 1-A、2-A、3-A = 计数 = 3 B - 5-B、8-B = 计数 = 2 C - 4-C、6-C = 计数 = 2

然后我需要返回数据集中匹配的记录集。

逻辑是合理的,我已经将它实现为运行良好的 Linq 查询,但在 30 多秒时太慢,无法在 API 调用结束时进行,因此我正在尝试对其进行优化。

似乎 MongoDB 实际上在返回数据方面非常快,所以我想我会将 guid 分成 x 长度的集合并并行化例程:

   var results = new List<Instance>();
   int counter = 0; int chunksize = 50;

   Parallel.For(0, (inputs.Count() / chunksize) + 1, x =>
   {
      var cx = inputs.Skip(chunksize * counter).Take(chunksize);

      foreach (var c in cx)
      {
         checkCounter++;
         $"Processing {c}".Dump();
         var instances = _db.Get<Instance>().Where(_Predicate_);
                if (instances.Any())
                {
                    results.AddRange(instances);
                    $"Total Instances is now: {results.Count()}".Dump();
                }
            }
            
        });

这似乎违反直觉(对我作为一个长期的 SQL 用户而言),但我认为它有腿。问题是当代码运行多个线程时,似乎从此处的列表中获取相同的 guid:

var cx = inputs.Skip(chunksize * counter).Take(chunksize);

当然,我需要确保为每个线程提供一组独特的 guid。我可以并行执行,还是应该考虑做一些更底层的事情,例如生成单独的任务?

谢谢阅读。

4

2 回答 2

2

您应该在循环中使用x而不是:counter

var cx = inputs.Skip(chunksize * x).Take(chunksize);

还可以使用线程安全集合之一results,或重构代码,以便生成批处理,然后并行处理它们。

于 2020-07-23T00:08:37.230 回答
1

您应该使用 Microsoft 的反应式框架(又名 Rx) - NuGetSystem.Reactive并添加using System.Reactive.Linq;- 然后您可以这样做:

IObservable<List<Instance>> query =
    from x in Observable.Range(0, (inputs.Count() / chunksize) + 1)
    from c in inputs.Skip(chunksize * x).Take(chunksize).ToObservable()
    from i in Observable.Start(() => _db.Get<Instance>().Where(_Predicate_).ToList())
    select i;

IList<List<Instance>> data = await query.ToList();

List<Instance> results = data.SelectMany(x => x).ToList();

注意x内的使用from c in inputs.Skip(chunksize * x).Take(chunksize).ToObservable()。那就是您的原始代码在使用counter.

此代码并行运行,并将自动构建最终列表,而无需担心List<Instance>.

LINQ 的使用也使代码非常易读。

于 2020-07-23T01:31:45.733 回答