繁体   English   中英

实体框架-数量绩效

[英]Entity Framework - Performance in count

我对实体框架的性能有些疑问。

就像是

using (MyContext context = new MyContext())
{
    Document DocObject = context.Document.Find(_id);
    int GroupCount = context.Document.Where(w=>w.Group == DocObject.Group).ToList().Count();
}

在我的数据库中(大约3万个数据集)大约需要2秒钟,而这一个

using (MyContext context = new MyContext())
{
    Document DocObject = context.Document.Find(_id);
    int GroupCount = context.Document.Where(w=>w.Group == DocObject.Group).Count();
}

需要0.02秒。

当我的10个文档过滤器需要等待20秒时,我检查了代码,并将其更改为在Count()之前不使用ToList() Count()

有什么主意为什么要用ToList()这行需要2秒?

调用ToList()然后再调用Count()将:

  • 对数据库执行整个SELECT FROM WHERE
  • 然后将所有结果实体具体化为.Net对象
  • 创建一个包含所有结果的新List<T>对象
  • 返回刚创建的.Net列表的Count属性的结果

针对IQueryable调用Count()将:

  • 对数据库执行SELECT COUNT FROM WHERE
  • 返回带有行数的Int32

显然,如果您只对项目的数量感兴趣( 而不对项目本身感兴趣),则永远不要首先调用ToList() ,因为它不需要很多资源。

是的,如果不使用ToList() ,则不会从数据库中检索对象,因此ToList()将评估结果(从数据库中检索对象)。

Linq-To-Entities默认情况下使用LazyLoading。

它的工作原理是这样的; 当您使用Linq-To-Entities查询基础数据库连接时,您将获得一个代理对象,可以在该对象上执行许多操作(计数为1)。 这意味着您不会立即从数据库中获取所有数据,而是在评估时从数据库中检索了对象。 评估对象的一种方法是使用ToList()。

也许你应该读这篇

因为ToList()将查询整个对象的数据库(会做一个SELECT *这么说的),然后你会使用Count()在内存中的列表上的所有记录,而如果你使用Count()IQueryable (不在List ),EF会将其转换为简单的SELECT COUNT(*) SQL查询

您的第一个查询未完全转换为sql-调用.ToList().Count() ,您基本上是在说“全部下载,将其具体化为POCO并调用名为Count()扩展方法”,这当然需要一些时间。

但是,您的第二个查询已转换为类似于select count(*) from Documents where GroupId = @DocObjectGroup ,执行起来要快得多,并且您无法实现任何东西,只是简单的标量。

使用扩展方法Enumerable.ToList()将从IEnumerable<T>源集合构造一个新的List对象,这意味着执行ToList()会产生相关的成本。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM