3

我最近在查询 SQL Server 2008 的实体框架时遇到了性能问题。我设法解决了这个问题,但我不明白为什么我的修复工作有效。我正在使用带有 .Contains() 方法的 Guid 集合在 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));

当有 > 150 个 ProjectID 时,此查询需要大约 20 秒才能执行。通过更改 .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 秒。

我敢肯定这有一个合理的理由,但我的好奇心正在扼杀我。它是什么?

4

3 回答 3

1

我的猜测是,在第二个通过其主键将马赫连接到项目的所有连接之后,第一个结果会导致 sql 中带有一堆或 OR 对工作项上的外键进行评估,并且只评估 150 个 id 然后将其加入其他表。

于 2012-06-25T19:48:47.327 回答
0

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

于 2012-06-25T19:42:23.430 回答
0

据我了解 Linq 的工作,它必须与查询的延迟执行有关。

在您的固定版本中,您有两个 Linq 表达式,它们将一个接一个地被评估和解释,但在您枚举结果时仅执行一次(如果有的话)。这巧妙地减少了数据库访问

第一个版本:

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

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

于 2012-06-25T19:48:01.297 回答