过滤内存收集:IQueryable提供更好的性能
本文关键字:更好 性能 IQueryable 内存 过滤 | 更新日期: 2023-09-27 17:49:55
假设我有一个内存中的集合(Persons),我必须对其应用一些过滤条件。
var distinctproductKeys = persons.Where(d => d.productsDictionary != null)
.SelectMany(d => d.productsDictionary.Keys)
.Distinct();
vs。如果我在应用过滤器之前使用IQueryable
var distinctproductKeys = persons.AsQueryable()
.Where(d => d.productsDictionary != null)
.SelectMany(d => d.productsDictionary.Keys)
.Distinct();
我读到,一旦你有你的集合在内存中,IQueryable和IEnumerable给出相同的性能。但是运行这两个查询,我观察到IQueryable版本更快。有人能告诉我为什么吗?
我不知道你是如何测试你的性能,但要记住的主要事情是当使用IQueryable和IEnumerable时,它们都会给你延迟执行。
与的区别在于IQueryable是允许LINQ-to- sql (LINQ. sql)的接口。(任何事情)都可以工作。因此,如果您进一步细化IQueryable查询,该查询将在数据库中执行,如果可能的话。
对于IEnumerable,它将是LINQ-to-object,这意味着所有匹配原始查询的对象都必须从数据库加载到内存中。
在代码:IQueryable<Customer> custs = ...;
// Later on...
var goldCustomers = custs.Where(c => c.IsGold);
该代码将执行SQL只选择金牌客户。另一方面,下面的代码将在数据库中执行原始查询,然后过滤掉内存中的非金牌客户:
IEnumerable<Customer> custs = ...;
// Later on...
var goldCustomers = custs.Where(c => c.IsGold);
这是一个非常重要的区别,使用IQueryable在很多情况下可以避免从数据库返回太多行。另一个典型的例子是分页:如果你在IQueryable上使用Take和Skip,你只会得到请求的行数;在IEnumerable上这样做会导致所有的行都被加载到内存中。