简体   繁体   English

EF LINQ ToList非常慢

[英]EF LINQ ToList is very slow

I am using ASP NET MVC 4.5 and EF6 , code first migrations. 我正在使用ASP NET MVC 4.5和EF6 ,代码首次迁移。

I have this code, which takes about 6 seconds. 我有这个代码,大约需要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

I thought that this is because of relations, it must build them inside memory, but that is not the case, because even when I return 0 fields, it is still as slow . 我认为这是因为关系,它必须在内存中构建它们,但事实并非如此, 因为即使我返回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

Now the Requests table is quite complex, lots of relations and has ~16k items. 现在请求表非常复杂,关系很多并且有大约16k项。 On the other hand, the filtered list should only contain proxies to 8 items. 另一方面,筛选后的列表应该只包含8个项目的代理。

Why is ToList() method so slow? 为什么ToList()方法这么慢? I actually think the problem is not in ToList() method, but probably EF issue, or bad design problem. 我实际上认为问题不在ToList()方法中,但可能是EF问题,或者设计问题不好。

Anyone has had experience with anything like this? 有没有经历过这样的事情?

EDIT: 编辑:

These are the conditions: 这些是条件:

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

So basically, I can checking if Student id is in my id list and checking if dates match. 所以基本上,我可以检查Student ID是否在我的ID列表中并检查日期是否匹配。

Your filtered variable contains a query which is a question , and it doesn't contain the answer . filtered变量包含一个问题的查询,但它不包含答案 If you request the answer by calling .ToList() , that is when the query is executed. 如果通过调用.ToList()请求答案,那就是执行查询时。 And that is the reason why it is slow, because only when you call .ToList() is the query executed by your database. 这就是为什么它很慢的原因,因为只有当你调用.ToList()才是数据库执行的查询。

It is called Deferred execution . 它被称为延迟执行 A google might give you some more information about it. 谷歌可能会给你一些关于它的更多信息。

If you show some of your conditions, we might be able to say why it is slow. 如果您展示了一些条件,我们可能会说出它为什么会变慢。

In addition to Maarten's answer I think the problem is about two different situation 除了Maarten的回答,我认为问题在于两种不同的情况

  1. some condition is complex and results in complex and heavy joins or query in your database some condition很复杂,会导致数据库中出现复杂和繁重的连接或查询

  2. some condition is filtering on a column which does not have an index and this cause the full table scan and make your query slow. some condition是对没有索引的列进行过滤,这会导致全表扫描并使查询变慢。

I suggest start monitoring the query generated by Entity Framework, it's very simple, you just need to set Log function of your context and see the results, 我建议开始监视实体框架生成的查询,它非常简单,你只需要设置上下文的Log函数并查看结果,

using (var context = new MyContext())
{
    context.Database.Log = Console.Write;

    // Your code here...
}

if you see something strange in generated query try to make it better by breaking it in parts, some times Entity Framework generated queries are not so good. 如果你在生成的查询中看到一些奇怪的东西,试着通过分解它来使它更好,有时实体框架生成的查询不是那么好。

if the query is okay then the problem lies in your database (assuming no network problem). 如果查询没问题,则问题出在您的数据库中(假设没有网络问题)。

run your query with an SQL profiler and check what's wrong. 使用SQL事件探查器运行查询并检查错误。

UPDATE UPDATE

I suggest you to: 我建议你:

  1. add index for StartDate and EndDate Column in your table (one for each, not one for both) 在表中添加StartDateEndDate列的索引(每个一个,而不是两个)

ToList executes the query against DB, while first line is not. ToList针对DB执行查询,而第一行则不执行。

Can you show some conditions code here? 你能在这里展示some conditions代码吗? To increase the performance you need to optimize query/create indexes on the DB tables. 要提高性能,需要优化数据库表上的查询/创建索引。

Your first line of code only returns an IQueryable . 您的第一行代码仅返回IQueryable This is a representation of a query that you want to run not the result of the query. 这是您要运行的查询的表示,而不是查询的结果。 The query itself is only runs on the databse when you call .ToList() on your IQueryable , because its the first point that you have actually asked for data. 当您在IQueryable上调用.ToList()时,查询本身仅在数据库上运行,因为它是您实际要求数据的第一个点。

Your adjustment to add the .Select only adds to the existing IQueryable query definition. 您添加.Select调整只会添加到现有的IQueryable查询定义中。 It doesnt change what conditions have to execute. 它不会改变必须执行的条件。 You have essentially changed the following, where you get back 8 records: 您基本上已更改以下内容,您将获得8条记录:

select * from Requests where [some conditions];

to something like: 类似于:

select '' from Requests where [some conditions];

You will still have to perform the full query with the conditions giving you 8 records, but for each one, you only asked for an empty string, so you get back 8 empty strings. 您仍然必须使用给出8条记录的条件执行完整查询,但是对于每条记录,您只需要一个空字符串,因此您将返回8个空字符串。

The long and the short of this is that any performance problem you are having is coming from your "some conditions". 这种情况的长期和不足之处在于,您遇到的任何性能问题都来自您的“某些条件”。 Without seeing them, its is difficult to know. 没有看到它们,很难知道。 But I have seen people in the past add .Where clauses inside a loop, before calling .ToList() and inadvertently creating a massively complicated query. 但我已经看到过去的人们在调用.ToList()之前添加了。循环中的子句,并且无意中创建了一个大规模复杂的查询。

Jaanus. Jaanus。 The most likely reason of this issue is complecity of generated SQL query by entity framework. 此问题最可能的原因是实体框架生成的SQL查询的强制性。 I guess that your filter condition contains some check of other tables. 我猜你的过滤条件包含一些其他表的检查。

Try to check generated query by "SQL Server Profiler". 尝试通过“SQL Server Profiler”检查生成的查询。 And then copy this query to "Management Studio" and check "Estimated execution plan". 然后将此查询复制到“Management Studio”并选中“Estimated execution plan”。 As a rule "Management Studio" generatd index recomendation for your query try to follow these recomendations. 作为规则“管理工作室”为您的查询生成索引建议尝试遵循这些建议。

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

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