EF LINQ ToList非常慢

我正在使用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.StartDate) 

基本上,我可以检查Student ID是否在我的ID列表中并检查日期是否匹配。

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

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

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

我建议开始监控Entity Framework生成的查询,它非常简单,你只需要设置上下文的Log函数并查看结果,

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

如果你在生成的查询中看到一些奇怪的东西,试图通过分解它来使它更好,有时entity framework生成的查询不是那么好。

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

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

UPDATE

我建议你:

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

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

它被称为延迟执行 。 谷歌可能会给你一些关于它的更多信息。

如果你展示了一些条件,我们可能会说出它为什么会变慢。

ToList对DB执行查询,而第一行则不执行。

你能在这里展示some conditions代码吗? 要提高性能,需要优化数据库表上的查询/创建索引。

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

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

 select * from Requests where [some conditions]; 

类似于:

 select '' from Requests where [some conditions]; 

您仍然必须使用给出8条记录的条件执行完整查询,但是对于每条记录,您只需要一个空字符串,因此您将返回8个空字符串。

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

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

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