实体框架6生成的非常低效的查询

Ken*_*ith 4 c# sql-server entity-framework

这是我想要的查询:

select top 10 *
from vw_BoosterTargetLog
where OrganizationId = 4125
order by Id desc
Run Code Online (Sandbox Code Playgroud)

它执行亚秒.

这是我的实体框架(6.1.2)在C#中的等价物:

return await db.vw_BoosterTargetLog
    .Where(x => x.OrganizationId == organizationId)
    .OrderByDescending(x => x.Id)
    .Take(numberToRun)
    .ToListNolockAsync();
Run Code Online (Sandbox Code Playgroud)

这是它生成的SQL:

SELECT TOP (10) 
    [Project1].[OrganizationId] AS [OrganizationId], 
    [Project1].[BoosterTriggerId] AS [BoosterTriggerId], 
    [Project1].[IsAutomatic] AS [IsAutomatic], 
    [Project1].[C1] AS [C1], 
    [Project1].[CustomerUserId] AS [CustomerUserId], 
    [Project1].[SourceUrl] AS [SourceUrl], 
    [Project1].[TargetUrl] AS [TargetUrl], 
    [Project1].[ShowedOn] AS [ShowedOn], 
    [Project1].[ClickedOn] AS [ClickedOn], 
    [Project1].[BoosterTargetId] AS [BoosterTargetId], 
    [Project1].[TriggerEventGroup] AS [TriggerEventGroup], 
    [Project1].[TriggerIgnoreIdentifiedUsers] AS [TriggerIgnoreIdentifiedUsers], 
    [Project1].[TargetTitle] AS [TargetTitle], 
    [Project1].[BoosterTargetVersionId] AS [BoosterTargetVersionId], 
    [Project1].[Version] AS [Version], 
    [Project1].[CookieId] AS [CookieId], 
    [Project1].[CoalescedId] AS [CoalescedId], 
    [Project1].[OrganizationName] AS [OrganizationName], 
    [Project1].[ShowedOnDate] AS [ShowedOnDate], 
    [Project1].[SampleGroupSectionName] AS [SampleGroupSectionName], 
    [Project1].[Selector] AS [Selector], 
    [Project1].[SelectorStep] AS [SelectorStep]
    FROM ( SELECT 
        [Extent1].[OrganizationId] AS [OrganizationId], 
        [Extent1].[OrganizationName] AS [OrganizationName], 
        [Extent1].[BoosterTriggerId] AS [BoosterTriggerId], 
        [Extent1].[IsAutomatic] AS [IsAutomatic], 
        [Extent1].[SampleGroupSectionName] AS [SampleGroupSectionName], 
        [Extent1].[Selector] AS [Selector], 
        [Extent1].[SelectorStep] AS [SelectorStep], 
        [Extent1].[BoosterTargetId] AS [BoosterTargetId], 
        [Extent1].[CookieId] AS [CookieId], 
        [Extent1].[CustomerUserId] AS [CustomerUserId], 
        [Extent1].[CoalescedId] AS [CoalescedId], 
        [Extent1].[SourceUrl] AS [SourceUrl], 
        [Extent1].[TriggerEventGroup] AS [TriggerEventGroup], 
        [Extent1].[TriggerIgnoreIdentifiedUsers] AS [TriggerIgnoreIdentifiedUsers], 
        [Extent1].[TargetTitle] AS [TargetTitle], 
        [Extent1].[TargetUrl] AS [TargetUrl], 
        [Extent1].[ShowedOn] AS [ShowedOn], 
        [Extent1].[ShowedOnDate] AS [ShowedOnDate], 
        [Extent1].[ClickedOn] AS [ClickedOn], 
        [Extent1].[BoosterTargetVersionId] AS [BoosterTargetVersionId], 
        [Extent1].[Version] AS [Version], 
         CAST( [Extent1].[Id] AS int) AS [C1]
        FROM (SELECT 
    [vw_BoosterTargetLog].[OrganizationId] AS [OrganizationId], 
    [vw_BoosterTargetLog].[OrganizationName] AS [OrganizationName], 
    [vw_BoosterTargetLog].[BoosterTriggerId] AS [BoosterTriggerId], 
    [vw_BoosterTargetLog].[IsAutomatic] AS [IsAutomatic], 
    [vw_BoosterTargetLog].[SampleGroupSectionName] AS [SampleGroupSectionName], 
    [vw_BoosterTargetLog].[Selector] AS [Selector], 
    [vw_BoosterTargetLog].[SelectorStep] AS [SelectorStep], 
    [vw_BoosterTargetLog].[BoosterTargetId] AS [BoosterTargetId], 
    [vw_BoosterTargetLog].[CookieId] AS [CookieId], 
    [vw_BoosterTargetLog].[CustomerUserId] AS [CustomerUserId], 
    [vw_BoosterTargetLog].[CoalescedId] AS [CoalescedId], 
    [vw_BoosterTargetLog].[Id] AS [Id], 
    [vw_BoosterTargetLog].[SourceUrl] AS [SourceUrl], 
    [vw_BoosterTargetLog].[TriggerEventGroup] AS [TriggerEventGroup], 
    [vw_BoosterTargetLog].[TriggerIgnoreIdentifiedUsers] AS [TriggerIgnoreIdentifiedUsers], 
    [vw_BoosterTargetLog].[TargetTitle] AS [TargetTitle], 
    [vw_BoosterTargetLog].[TargetUrl] AS [TargetUrl], 
    [vw_BoosterTargetLog].[ShowedOn] AS [ShowedOn], 
    [vw_BoosterTargetLog].[ShowedOnDate] AS [ShowedOnDate], 
    [vw_BoosterTargetLog].[ClickedOn] AS [ClickedOn], 
    [vw_BoosterTargetLog].[BoosterTargetVersionId] AS [BoosterTargetVersionId], 
    [vw_BoosterTargetLog].[Version] AS [Version]
    FROM [dbo].[vw_BoosterTargetLog] AS [vw_BoosterTargetLog]) AS [Extent1]
        WHERE [Extent1].[OrganizationId] = 4125
    )  AS [Project1]
    ORDER BY [Project1].[C1] DESC
Run Code Online (Sandbox Code Playgroud)

当然,这很糟糕,因为所有EF查询都是:我不是在抱怨.我的抱怨是,在我的测试中,最好的情况是,它比第一个慢了大约10倍,最坏的情况下,大约慢100倍.

对于一个简单的查询,这似乎超出了所有合理的期望.

显然我可以直接执行SQL,或者执行一个sproc,或者那种类型的东西.虽然我在等待反馈,但这就是我要做的.但有没有人有任何其他建议如何加快速度?有没有办法鼓励EF在这种情况下生成合理的SQL?

Jer*_*ert 9

查询EF产生,而从可读性的角度可怕,通常还是相当不错的合理的-我说,谁的人通过与手写查询存储过程,则几乎所有的数据访问.但是为了使它工作,模型EF的数据库需要与实际数据库匹配,否则将引入转换,当发生这种情况时,容易在所有数据转换而没有索引的情况下获得可怕的性能下降可以使用.

如果我们消除了一些嵌套,EF查询可以简化为

SELECT TOP (10) *
FROM (
    SELECT *, CAST(Id AS INT) AS C1
    FROM vw_BoosterTargetLog
    WHERE OrganizationId = 4125
) _
ORDER BY C1 DESC
Run Code Online (Sandbox Code Playgroud)

(这不是实际的结果集,因为Id它不是真实查询中最终结果集的一部分,但假装我像EF那样写出了所有列.)

如果vw_BoosterTargetLog.Id实际上不是INTa,则在排序发生之前强制转换所有行,这要慢得多.解决方案是找出列的实际类型(在本例中BIGINT),并相应地更新模型.