C# PLINQ 内存列表查询优化历程
问题描述
我们有一个包含1千万个元素的列表,每个元素包含两个整数字段,需要进行查询和统计操作。最初使用普通的Linq查询,但在大数据情况下性能明显不足。
解决方案
我们使用PLINQ(Parallel LINQ,即并行LINQ)来优化查询。PLINQ是Linq的一个扩展,可以在多个线程中并行执行查询,提高查询效率。
步骤1 原始查询
使用普通的Linq查询,代码如下:
var result = data.Where(x => x.Field1 == value1 && x.Field2 == value2)
.GroupBy(x => x.Field3)
.Select(x => new { Field3 = x.Key, Count = x.Count() })
.OrderByDescending(x => x.Count)
.ToList();
步骤2 利用PLINQ并行化查询
对于大型数据集,可以使用PLINQ将查询并行执行。PLINQ不仅可以简化代码,而且可以在多个CPU核心上并行执行查询,提高查询效率。
var result = data
.AsParallel() //使用PLINQ并行化查询
.Where(x => x.Field1 == value1 && x.Field2 == value2)
.GroupBy(x => x.Field3)
.Select(x => new { Field3 = x.Key, Count = x.Count() })
.OrderByDescending(x => x.Count)
.ToList();
步骤3 增加任务并行数
PLINQ默认使用的任务数是CPU核心数,可以通过WithDegreeOfParallelism
方法设置并行任务数,进一步提高查询效率。
var result = data
.AsParallel().WithDegreeOfParallelism(4) //设置并行任务数为4
.Where(x => x.Field1 == value1 && x.Field2 == value2)
.GroupBy(x => x.Field3)
.Select(x => new { Field3 = x.Key, Count = x.Count() })
.OrderByDescending(x => x.Count)
.ToList();
步驟4 全局禁用PLINQ默认缓存
当数据量非常大时,PLINQ默认缓存极有可能把大量内存占用,从而引发内存溢出,甚至机器宕机。可以通过禁用PLINQ默认缓存避免这些问题。
var result = data
.AsParallel().WithDegreeOfParallelism(4)
.WithMergeOptions(ParallelMergeOptions.FullyBuffered) //全局禁用PLINQ默认缓存
.Where(x => x.Field1 == value1 && x.Field2 == value2)
.GroupBy(x => x.Field3)
.Select(x => new { Field3 = x.Key, Count = x.Count() })
.OrderByDescending(x => x.Count)
.ToList();
示例说明
示例1:简单Linq查询
假设我们有一个包含一千万个整数的列表,需要查询和统计大于100的个数,代码如下:
var data = Enumerable.Range(1, 10000000).ToList();
var result = data.Where(x => x > 100).Count();
示例2:使用PLINQ提高查询效率
我们将上述查询语句改成使用PLINQ并行化查询:
var data = Enumerable.Range(1, 10000000).ToList();
var result = data.AsParallel().Where(x => x > 100).Count();
通过PLINQ并行化查询,即使我们有大数据集,统计查询结果也可以更快地完成。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C# PLINQ 内存列表查询优化历程 - Python技术站