Linq2Entities +实体框架查询优化:.Where() 与 Linq where

发布于 2024-11-01 00:20:35 字数 2202 浏览 1 评论 0原文

我对我的实体框架模型进行了一个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

柒七 2024-11-08 00:20:35

这些查询之间的区别在于表示您使用的构造。第一个查询的计算结果为,

 (from e3 in context.Entity3) where e3.Fied1 == value

而第二个查询的计算结果为

 from e3 in (context.Entity3.Where(e => e.Field1 == value))

点语法优先,因为它被视为单独的表达式子树,必须构建该子树并将其附加到外部查询的表达式树。您可以将其视为子查询,即使它不一定是最后的子查询,如示例所示。

The difference between these queries is in representing constructs you used. The first query is evaluated as

 (from e3 in context.Entity3) where e3.Fied1 == value

whereas second query is evaluated as

 from e3 in (context.Entity3.Where(e => e.Field1 == value))

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文