Linq2Entities +实体框架查询优化:.Where() 与 Linq where
我对我的实体框架模型进行了一个 Linq 查询,类似于:
from e1 in context.Entity1
from e2 in context.Entity2
from e3summary in
from e3 in context.Entity3
where e3.Field1 = value // <-- this is the line in question
group e3 by new { e3.Field1, e3.Field2, e3.Field3 }
into e3group
select new
{
e3group.Key.Field1,
e3group.Key.Field2,
e3group.Key.Field3,
Total = e3group.Sum(o => o.Field4)
}
where
// conditions on e1 and joining e1, e2, and e3summary
...
select e1;
生成的 SQL 从我的 e3 表(实际上是数据库中的视图)中选择所有内容作为派生表,然后对派生表应用 where 子句,将其分组,并加入我的其他结果。这几乎正是我想要的,只是我认为我不需要对整个 e3 视图进行分组(我的测试数据库中有 73M 条记录,生产中几乎有 800M 条记录)。我原本期望 Linq 查询中的 WHERE 子句应用于最内层,但我得到的是(我只包含相关部分):
...
INNER JOIN (SELECT
[Extent3].[Field1] AS [K1],
[Extent3].[Field2] AS [K2],
[Extent3].[Field3] AS [K3],
SUM([Extent3].Field4] AS [A1]
FROM (SELECT
[e3].[ID] AS [ID],
[e3].[Field1] AS [Field1],
[e3].[Field2] AS [Field2],
[e3].[Field3] AS [Field3],
[e3].[Field4] AS [Field4],
[e3].[Field5] AS [Field5],
[e3].[Field6] AS [Field6],
[e3].[Field7] AS [Field7],
[e3].[Field8] AS [Field8]
FROM [dbo].[e3] AS [e3]) AS [Extent3]
WHERE ([Extent3].[Field1] = @p__linq__0)
GROUP BY [Extent3].[Field1], [Extent3].[Field2], [Extent3].[Field3] ) AS [GroupBy1]
...
我将 Linq 查询从 更改为
from e3 in context.Entity3
where e3.Field1 = value // <-- this is the line in question
,
from e3 in context.Entity3.Where(e => e.Field1 = value)
这创建了我最初期望的内容,最内层的 WHERE 子句:
...
FROM [dbo].[e3] AS [e3] WHERE [e3].Field1] = @p__linq__0) AS [Extent3]
GROUP BY [Extent3].[Field1], [Extent3].[Field2], [Extent3].[Field3] ) AS [GroupBy1]
为什么直接针对我的上下文中的集合应用 .Where([condition])
与使用 where [我的 Linq 查询中的条件]
?我认为这会以同样的方式解析到表达式树中。
PS 顺便说一句,将两个查询放入 SQL Server Management Studio 并比较查询执行计划,我惊讶地发现执行计划完全相同。 SQL的查询计划优化器真是不可思议!
I had a Linq query against my Entity Framework model that was something like:
from e1 in context.Entity1
from e2 in context.Entity2
from e3summary in
from e3 in context.Entity3
where e3.Field1 = value // <-- this is the line in question
group e3 by new { e3.Field1, e3.Field2, e3.Field3 }
into e3group
select new
{
e3group.Key.Field1,
e3group.Key.Field2,
e3group.Key.Field3,
Total = e3group.Sum(o => o.Field4)
}
where
// conditions on e1 and joining e1, e2, and e3summary
...
select e1;
The SQL that was generated was selecting everything from my e3 table (actually a view in the database) as a derived table, then applying the where clause against the derived table, grouping that, and joining to my other results. That's almost exactly what I wanted, except I thought I didn't need the whole e3 view to be grouped (it's 73M records in my test database, almost 800M in production). I was expecting the WHERE clause in my Linq query to be applied at the inner-most level, but instead I was getting (I'm including only the relevant part):
...
INNER JOIN (SELECT
[Extent3].[Field1] AS [K1],
[Extent3].[Field2] AS [K2],
[Extent3].[Field3] AS [K3],
SUM([Extent3].Field4] AS [A1]
FROM (SELECT
[e3].[ID] AS [ID],
[e3].[Field1] AS [Field1],
[e3].[Field2] AS [Field2],
[e3].[Field3] AS [Field3],
[e3].[Field4] AS [Field4],
[e3].[Field5] AS [Field5],
[e3].[Field6] AS [Field6],
[e3].[Field7] AS [Field7],
[e3].[Field8] AS [Field8]
FROM [dbo].[e3] AS [e3]) AS [Extent3]
WHERE ([Extent3].[Field1] = @p__linq__0)
GROUP BY [Extent3].[Field1], [Extent3].[Field2], [Extent3].[Field3] ) AS [GroupBy1]
...
I changed my Linq query from
from e3 in context.Entity3
where e3.Field1 = value // <-- this is the line in question
to
from e3 in context.Entity3.Where(e => e.Field1 = value)
and this created what I originally expected, the WHERE clause at the inner-most level:
...
FROM [dbo].[e3] AS [e3] WHERE [e3].Field1] = @p__linq__0) AS [Extent3]
GROUP BY [Extent3].[Field1], [Extent3].[Field2], [Extent3].[Field3] ) AS [GroupBy1]
Why would there be a difference between applying a .Where([condition])
directly against the collection in my context vs. having a where [condition]
in my Linq query? I would think this would get parsed into the expression tree the same way.
P.S. On a sidenote, putting both queries into SQL Server Management Studio and comparing the query execution plan, I was surprised to find the execution plan was exactly the same either way. SQL's query plan optimizer really is incredible!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这些查询之间的区别在于表示您使用的构造。第一个查询的计算结果为,
而第二个查询的计算结果为
点语法优先,因为它被视为单独的表达式子树,必须构建该子树并将其附加到外部查询的表达式树。您可以将其视为子查询,即使它不一定是最后的子查询,如示例所示。
The difference between these queries is in representing constructs you used. The first query is evaluated as
whereas second query is evaluated as
Dotted syntax takes precedence because it is taken as separate expression subtree which must be constructed and attached to expression tree of the outer query. You can think about it as subquery even it doesn't have to be subquery at the end as shown in your example.