EF LINQ ToList非常慢

时间:2014-11-04 10:49:31

标签: c# .net linq entity-framework ef-code-first

我正在使用ASP NET MVC 4.5和EF6,代码首次迁移。

我有这段代码,大约需要6秒钟。

var filtered = _repository.Requests.Where(r => some conditions); // this is fast, conditions match only 8 items
var list = filtered.ToList(); // this takes 6 seconds, has 8 items inside

我认为这是因为关系,它必须在内存中构建它们,但事实并非如此,因为即使我返回0字段,它仍然很慢

var filtered = _repository.Requests.Where(r => some conditions).Select(e => new {}); // this is fast, conditions match only 8 items
var list = filtered.ToList(); // this takes still around 5-6 seconds, has 8 items inside

现在请求表非常复杂,关系很多并且有大约16k项。另一方面,筛选后的列表应该只包含8个项目的代理。

为什么ToList()方法这么慢?我实际上认为问题不在ToList()方法中,但可能是EF问题,或者是设计问题。

任何人都有过这样的经历吗?

修改

以下是条件:

_repository.Requests.Where(r => ids.Any(a => a == r.Student.Id) && r.StartDate <= cycle.EndDate && r.EndDate >= cycle.StartDate)

基本上,我可以检查{id}列表中是否有Student id并检查日期是否匹配。

5 个答案:

答案 0 :(得分:6)

您的filtered变量包含问题的查询,但不包含答案。如果您通过调用.ToList()请求答案,那就是执行查询的时间。这就是为什么它很慢的原因,因为只有当你调用.ToList()时才是数据库执行的查询。

它被称为延迟执行A google可能会为您提供更多相关信息。

如果你展示了一些条件,我们或许可以说明为什么它很慢。

答案 1 :(得分:3)

除了Maarten的回答,我认为问题是关于两种不同的情况

  1. some condition很复杂,会导致数据库中出现复杂繁重的连接或查询

  2. some condition正在对没有索引的列进行过滤,这会导致全表扫描并使查询变慢。

  3. 我建议开始监控实体框架生成的查询,这非常简单,您只需要设置上下文的Log函数并查看结果,

    using (var context = new MyContext())
    {
        context.Database.Log = Console.Write;
    
        // Your code here...
    }
    

    如果你在生成的查询中看到一些奇怪的东西,试着通过将它分成几部分来改善它,有时候实体框架生成的查询不太好。

    如果查询没问题则问题在于您的数据库(假设没有网络问题)。

    使用SQL事件探查器运行查询并检查错误。

    <强>更新

    我建议你:

    1. 在表格中添加StartDateEndDate列的索引(每个列一个,而不是两个)

答案 2 :(得分:2)

ToList执行针对DB的查询,而第一行不是。

您可以在此处显示some conditions代码吗? 要提高性能,需要优化数据库表上的查询/创建索引。

答案 3 :(得分:1)

您的第一行代码只返回IQueryable。这是您要运行的查询的表示,而不是查询的结果。当您在.ToList()上调用IQueryable时,查询本身仅在数据库上运行,因为它是您实际要求数据的第一个点。

添加.Select的调整只会添加到现有的IQueryable查询定义中。它不会改变必须执行的条件。您已经基本上更改了以下内容,您将获得8条记录:

select * from Requests where [some conditions];

类似于:

select '' from Requests where [some conditions];

您仍然必须使用给出8条记录的条件执行完整查询,但是对于每条记录,您只需要一个空字符串,这样您就可以获得8个空字符串。

长期和短期是你遇到的任何性能问题都来自你的“某些条件”。没有看到它们,很难知道。但我已经看到过去的人们在调用.ToList()并无意中创建了一个大规模复杂的查询之前添加了。循环中的子句。

答案 4 :(得分:0)

Jaanus。此问题最可能的原因是实体框架生成的SQL查询的强制性。我猜你的过滤条件包含一些其他表的检查。

尝试通过“SQL Server Profiler”检查生成的查询。然后将此查询复制到“Management Studio”并选中“Estimated execution plan”。通常,“Management Studio”会根据您的查询生成索引建议,请尝试遵循这些建议。