【问题标题】:Filtering in-memory collection: does IQueryable give better performance?过滤内存集合:IQueryable 是否提供更好的性能?
【发布时间】:2014-03-12 19:05:25
【问题描述】:

假设我有一个内存集合(Persons),我必须在其上应用一些过滤条件。

var distinctproductKeys = persons.Where(d => d.productsDictionary != null)
                                 .SelectMany(d => d.productsDictionary.Keys)
                                 .Distinct();

对比如果我在应用过滤器之前使用 IQueryable

var distinctproductKeys = persons.AsQueryable()
                                 .Where(d => d.productsDictionary != null)
                                 .SelectMany(d => d.productsDictionary.Keys)
                                 .Distinct();

我已经读过,一旦你在内存中收集了集合,IQueryable 和 IEnumerable 都会提供相同的性能。但是运行我观察到的 IQueryable 版本的两个查询更快。有人能告诉我为什么吗?

【问题讨论】:

  • Persons 是什么类型的?
  • 你能告诉我们,你是如何测试它的,你得到了什么结果?

标签: c# performance entity-framework ienumerable iqueryable


【解决方案1】:

我不知道你是如何测试你的性能的,但是在使用 IQueryableIEnumerable 时要记住的主要事情是,它们都会给你 deferred执行

区别是 IQueryable 是允许 LINQ-to-SQL(LINQ.-to-anything)工作的接口。因此,如果您在 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 上执行此操作会导致所有行都加载到内存中。

【讨论】:

  • IEnumerable 让我立即执行,例如 IEnumerable list = query.Where(p => p.Title.Contains("first")).AsEnumerable();在 foreach 之前将查询放入数据库
猜你喜欢
  • 2011-01-11
  • 2016-12-03
  • 1970-01-01
  • 1970-01-01
  • 2020-03-02
  • 2021-12-24
  • 2018-02-03
  • 2012-11-26
  • 1970-01-01
相关资源
最近更新 更多