我最近在实体框架查询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秒。
我确信这是一个理智的理由,但我的好奇心正在扼杀我。它是什么?
答案 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
中!