我有两个内存列表播放和消费者,一个有 1500 万个对象,另一个有大约 300 万个对象。
以下是我正在触发的一些查询..
consumersn=consumers.AsParallel()
.Where(w => plays.Any(x => x.consumerid == w.consumerid))
.ToList();
List<string> consumerids = plays.AsParallel()
.Where(w => w.playyear == group_period.year
&& w.playmonth == group_period.month
&& w.sixteentile == group_period.group)
.Select(c => c.consumerid)
.ToList();
int groupcount = plays.AsParallel()
.Where(w => w.playyear == period.playyear
&& w.playmonth == period.playmonth
&& w.sixteentile == group
&& consumerids.Any(x => x == w.consumerid))
.Count();
我使用的是 16 核机器和 32 GB RAM,尽管如此..第一个查询运行了大约 20 小时..
我是不是做错了什么..
真诚感谢所有帮助。
谢谢
最佳答案
第一个 LINQ 查询效率很低,并行化只能帮到你这么多。
解释:当你写consumers.Where(w => plays.Any(x => x.consumerid == w.consumerid))
,这意味着对于 consumer
中的每个对象,您可能会遍历整个 plays
列表以查找受影响的消费者。因此,最多 300 万消费者乘以 1500 万次播放 = 45 万亿次操作。即使在 16 个内核中,每个内核也大约有 2.8 万亿次操作。
因此,这里的第一步是按 consumerId 对所有播放进行分组,并将结果缓存在适当的数据结构中:
var playsByConsumerIds = plays.ToLookup(x => x.consumerid, StringComparer.Ordinal);
然后,您的第一个请求变为:
consumersn = consumers.Where(w => playsByConsumerIds.Contains(w.consumerid)).ToList();
这个查询应该更快,即使没有任何并行化也是如此。
我无法修复以下查询,因为我看不到你在使用 group_period
做什么, 但我建议使用 GroupBy
或 ToLookup
一次创建所有组。
关于c# - 大型列表上的 plinq 需要花费大量时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39952453/