Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实体框架6生成的查询效率极低_C#_Sql Server_Entity Framework - Fatal编程技术网

C# 实体框架6生成的查询效率极低

C# 实体框架6生成的查询效率极低,c#,sql-server,entity-framework,C#,Sql Server,Entity Framework,以下是我想要的查询: select top 10 * from vw_BoosterTargetLog where OrganizationId = 4125 order by Id desc 它执行亚秒 以下是我的实体框架6.1.2在C中的等效版本: return await db.vw_BoosterTargetLog .Where(x => x.OrganizationId == organizationId) .OrderByDescending(x =>

以下是我想要的查询:

select top 10 *
from vw_BoosterTargetLog
where OrganizationId = 4125
order by Id desc
它执行亚秒

以下是我的实体框架6.1.2在C中的等效版本:

return await db.vw_BoosterTargetLog
    .Where(x => x.OrganizationId == organizationId)
    .OrderByDescending(x => x.Id)
    .Take(numberToRun)
    .ToListNolockAsync();
下面是它生成的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
当然,这和所有EF查询一样难看:我不是在抱怨。我的抱怨是,在我的测试中,最好的情况下,它的执行速度比第一个慢10倍,最坏的情况下,大约慢100倍

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


显然,我可以直接执行SQL,或者执行存储过程,或者类似的东西。当我在等待反馈时,我会这么做。但是,对于如何加快这一进程,有人还有其他建议吗?在这种情况下,有没有办法鼓励EF生成合理的SQL?

EF生成的查询虽然从可读性的角度来看很糟糕,但通常还是相当合理的——我要说的是,作为一个几乎通过存储过程手工编写查询来访问所有数据的人。但为了使其正常工作,数据库的EF模型需要与实际数据库匹配,否则将引入转换,当这种情况发生时,很容易在转换所有数据且无法使用索引的情况下获得可怕的性能下降

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

选择前10名* 从…起 选择*,CASTId作为INT作为C1 来自vw_BoosterTargetLog 其中OrganizationId=4125 _ 按C1说明订购 这不是实际的结果集,因为Id不是实际查询中最终结果集的一部分,但假设我像EF一样写出了所有列


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

出于好奇,vw_BoosterTargetLog.ID的列类型是什么?我假设通过您的命名,vw意味着它是一个视图?EF和视图不协调。。。在尝试使用它们时,您总是会遇到各种问题。EF不知道如何优化视图。它不知道PK是什么。它不知道实际支持表中有任何元数据……除了不合理的可读性之外,EF生成的查询实际上并没有那么多,优化器应该生成一个与您上面介绍的简单查询相同的计划。我在列类型之后询问的原因是,查询中的CAST[Extent1].[Id]显示为int-如果该列不是int类型,转换会使生成的顺序效率极低,因为SQL Server必须先转换所有值,然后才能对它们进行排序。但是,如果基础列是INT,那么优化器应该能看穿它。@jeroenmoster-Ah!在你的评论之后,我仔细检查了一遍,结果发现我撒谎了。它实际上是一个BIGINT。这可能就是问题所在。所以问题变成了我如何让EF识别它为long/Int64,我想。好了。虽然从整数类型转换为更大的整数类型是没有问题的,但在排序之后将完成转换,反之则会强制在排序之前执行转换步骤,从而进行完整的表扫描。您使用的是模型优先还是代码优先?对于代码优先,我认为您可以自由地将实体中的属性类型更改为应该的类型。对于model first,您可以随意摆弄模型,但我不知道如何在EF重新生成模型时使更改保持不变。很好的捕获,很好的解释。谢谢