LINQ简单查询需要30多秒钟

时间:2018-09-07 10:34:45

标签: c# linq

使用EF进行非常简单的查询时遇到问题。 以下查询需要30多个秒才能运行,并引发超时错误:

var results = _Context.Entity
            .Where(x => list1.Contains(x.Id))
            .Where(x => !list2.Contains(x.Id))
            .ToList();

下面的一个运行时间为1/4秒:

var results = _Context.Entity
            .Where(x => list1.Contains(x.Id))
            .ToList();

results = results
            .Where(x => !list2.Contains(x.Id))
            .ToList();

数据库中的集合大约有60k行,而我的两个列表都是大约5k int。 这是缓存问题吗?我的应用程序中有很多类似的查询,都可以顺利运行。我该怎么做才能改善它?

2 个答案:

答案 0 :(得分:1)

在情况1中,您将构建一个更复杂的查询,如下所示:

SELECT * FROM Entities WHERE Id in (...) AND Id NOT IN (...)

但是在第2种情况下,您可以进行简单的查询

SELECT * FROM Entities WHERE Id in (...)

,然后用C#过滤出结果。如果您的list2实际上是HashSet,它将更快地工作。但是,您使SQL Server返回多余的行,这些行将被过滤掉。

我想,第一个的工作速度较慢,因为它不利用索引,但是我不确定,我可能是错的。

更重要的是,您真正想要的是获取ID在list1中而不是list2中的所有项目。在这种情况下,您不需要让SQL Server处理它-只需用代码过滤掉它,然后仅传递您需要的ID:

var listToSearch = list1.Except(list2).ToArray();
var results = _Context.Entity.Where(x => listToSearch.Contains(x.Id)).ToList();

答案 1 :(得分:0)

您的第一个是检查将SQL运行到where条件。

SELECT * FROM Entity WHERE id IN () AND id NOT IN ()

第二个仅在查询中运行检查的地方:

SELECT * FROM Entity WHERE id IN ()

检查第二个语句的第二个语句的位置:

results = results
        .Where(x => !list2.Contains(x.Id))
        .ToList();

实际上是在Web服务器上运行,而不是使用sql。键入.ToList()后,立即执行SQL Linq。

无论如何,第一个要慢于第二个的原因是因为它将Entity中的每个元素都与两个列表进行了比较。第二步在哪里检查id是否在列表中,然后返回满足该条件的项目列表。然后,程序将使用返回的过滤列表(很可能少于实体表中某些表的总行数)进行检查,以确保该列表中不包含ID为列表2的行。

所以第二个只是比较少了。