实体框架两个查询具有相同的结果,但一个查询速度更快

时间:2012-06-25 19:33:54

标签: c# .net sql-server entity-framework

我最近在实体框架查询SQL Server 2008时遇到了性能问题。我设法解决了这个问题,但我不明白为什么我的修复工作正常。我正在使用一个带有.Contains()方法的Guids集合来在SQL中生成一个IN子句。这是原始代码(更改表名以保护无辜者):

Guid[] values = filter.Split(',').Select<String, Guid>(d => new Guid(d)).ToArray();


returnValue = returnValue.Where(t => values.Contains(t.WorkItem.Requirement.Project.ProjectId));

当有&gt;时,此查询需要约20秒才能执行150项目ID。通过改变.Contains()的位置,我可以大大加快速度。这是重构:

Guid[] values = filter.FilterValue.Split(',').Select<String, Guid>(d => new Guid(d)).ToArray();

var projects = from p in context.DC_DEF_Project
               where values.Contains(p.ProjectId)
               select p;

returnValue = from t in returnValue
              join p in projects on t.DC_DEF_ProjectWorkItem.DC_DEF_ProjectRequirement.ProjectId equals p.ProjectId
              select t;

此代码在与上述查询相同的数据集上花费约0.125秒。

我确信这是一个理智的理由,但我的好奇心正在扼杀我。它是什么?

3 个答案:

答案 0 :(得分:1)

我的猜测是第一个导致sql带有一堆或ORs在工作项上的外键之后进行评估,其中第二个连接是第二个通过它的主键连接到项目并仅评估150个ID然后加入到其他表格。

答案 1 :(得分:0)

我认为在第一个示例中,您将整个数据集转移到您的应用程序,然后针对它进行内存中的linq查询。

答案 2 :(得分:0)

据我所知,Linq的工作必须与延迟执行查询有关。

在您的固定版本中,您有两个Linq表达式,这些表达式将被评估并解释为一个接一个,但在枚举结果时仅执行 如果有的话)。整齐地减少了数据库访问

第一个版本:

returnValue.Where(t => values.Contains(t.WorkItem.Requirement.Project.ProjectId))

在第一步中执行任何过滤。它将检查当前表格行的ProjectId是否包含在表格的每一行values中!