我有两个内存列表播放和消费者一个有15密耳的对象,另一个有3密耳。
以下是我要解雇的一些问题。
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个小时才能运行..
我做错了什么..
真诚感谢所有帮助。
由于
答案 0 :(得分:2)
第一个LINQ查询效率非常低,并行化只能帮助你。
说明:当您编写consumers.Where(w => plays.Any(x => x.consumerid == w.consumerid))
时,这意味着,对于consumer
中的每个对象,您可能会遍历整个plays
列表以查找受影响的使用者。因此,最多300万消费者乘以1500万次播放= 45万亿次播放。即使在16个核心中,每个核心也有大约2.8万亿次操作。
所以,这里的第一步是按照consumerIds对所有播放进行分组,并将结果缓存到适当的数据结构中:
var playsByConsumerIds = plays.ToLookup(x => x.consumerid, StringComparer.Ordinal);
然后,您的第一个请求变为:
consumersn = consumers.Where(w => playsByConsumerIds.Contains(w.consumerid)).ToList();
即使没有任何并行化,此查询也应该更快。
我无法修复以下查询,因为我没有确切地看到您正在使用group_period
完成的操作,但我建议您使用GroupBy
或ToLookup
来创建所有组单程。
答案 1 :(得分:1)
第一个查询需要20个小时才能运行,因为每次plays.Any(x => x.consumerid == w.consumerid)
不存在时,consumerid
需要遍历整个15,000,000个游戏列表。
您可以通过在plays
中构建所有使用者ID的哈希集来加快速度,如下所示:
var consumerIdsInPlays = new HashSet<string>(plays.Select(p => p.consumerid));
现在可以为O(1)查找重写第一个查询:
consumersn=consumers
.AsParallel()
.Where(w => consumerIdsInPlays.Contains(w.consumerid))
.ToList();