表现:.Join vs .Contains - Linq to Entities

Gir*_*hel 8 c# sql-server lambda linq-to-entities entity-framework

我使用Linq实体来查询数据库以获取int列表以供进一步处理.我有两种方法可以获得如下列表:

首先是:

List<int> lstBizIds = new List<int>() { 1, 2, 3, 4, 5 };
List<int> lstProjectIds = context.Projects.Where(x => lstBizIds.Contains(x.businessId)).Select(x => x.projectId).ToList();
Run Code Online (Sandbox Code Playgroud)

第二是:

List<int> lstBizIds = new List<int>() { 1, 2, 3, 4, 5 };
List<int> lstProjectIds = context.Projects.Join(lstBizIds, p => p.businessId, u => u, (p, u) => p.projectId).ToList();
Run Code Online (Sandbox Code Playgroud)

现在我的问题是上面哪种方法更好的表现?如果第一个列表即lstBizIds的大小增加,它是否也会影响性能?如果性能降低,建议我实施其他方法.

Sef*_*efe 6

您应该使用Contains,因为EF可以产生更有效的查询。

这将是SQL连接:

SELECT Id
FROM Projects
INNER JOIN (VALUES (1), (2), (3), (4), (5)) AS Data(Item) ON Projects.UserId = Data.Item
Run Code Online (Sandbox Code Playgroud)

这将是SQL包含的内容:

SELECT Id
FROM Projects
WHERE UserId IN (1, 2, 3, 4, 5, 6)
Run Code Online (Sandbox Code Playgroud)

INJOINDBMS可以停止寻找的第一个匹配项更有效INJOIN即使在第一场比赛之后,总会结束。

您可能还需要检查哪些查询实际上已发送到数据库。您总是必须比较SQL,而不是LINQ代码(显然)。

  • 请注意,对于较大的集合(例如&gt; 1000个项目),在实体框架中,包含的速度非常慢。由于内部原因,它很慢,而不是因为生成的查询很慢。因此,因此-最好不要在大型​​集合上使用Contains。 (6认同)
  • 您对生成的SQL是正确的(尽管SqlServer的`join`看起来有所不同)+1。但不是哪一个更有效-真正取决于数据库查询计划优化器。大多数现代的查询优化器都会产生一个相同的执行计划。 (5认同)

g.0*_*005 2

执行联接非常高效,因为Where条件实际上执行所有表的笛卡尔积,然后过滤满足条件的行。这意味着对每个行组合 (n1 * n2 * n3 * n4) 评估Where 条件

Join 运算符从第一个表中获取行,然后仅从第二个表中获取具有匹配键的行,然后仅从第三个表中获取具有匹配键的行,依此类推。其次,contains 将以迭代方式工作,使其比 join 慢

  • 这适用于 LINQ to Objects,但问题是关于 LINQ to Entities。 (2认同)